chore: 并入 iotlcm-admin-ui 历史到 admin-ui/(原提交 f305eab)
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# 应用标题
|
||||
VITE_APP_TITLE=物联网全生命周期管理平台
|
||||
VBEN_LOGO_URL=/images/logo.png
|
||||
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
||||
VITE_APP_NAMESPACE=iotlcm-admin-web
|
||||
# 客户端ID
|
||||
VITE_GLOB_CLIENT_ID=your-client-id
|
||||
# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密
|
||||
VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key
|
||||
@@ -0,0 +1,7 @@
|
||||
# public path
|
||||
VITE_BASE=/
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
VITE_VISUALIZER=true
|
||||
@@ -0,0 +1,19 @@
|
||||
# 端口号
|
||||
VITE_PORT=5666
|
||||
|
||||
VITE_BASE=/
|
||||
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
|
||||
VITE_NITRO_MOCK=false
|
||||
|
||||
# 是否打开 devtools,true 为打开,false 为关闭
|
||||
VITE_DEVTOOLS=false
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
||||
|
||||
# 客户端ID
|
||||
VITE_GLOB_CLIENT_ID=your-client-id
|
||||
@@ -0,0 +1,22 @@
|
||||
VITE_BASE=/
|
||||
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
# 是否开启压缩,可以设置为 none, brotli, gzip
|
||||
VITE_COMPRESS=none
|
||||
|
||||
# 是否开启 PWA
|
||||
VITE_PWA=false
|
||||
|
||||
# vue-router 的模式
|
||||
VITE_ROUTER_HISTORY=hash
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
||||
|
||||
# 打包后是否生成dist.zip
|
||||
VITE_ARCHIVER=true
|
||||
|
||||
# 客户端ID
|
||||
VITE_GLOB_CLIENT_ID=your-client-id
|
||||
@@ -0,0 +1,48 @@
|
||||
<!doctype html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="description" content="A Modern Back-end Management System" />
|
||||
<meta name="keywords" content="Vben Admin Vue3 Vite" />
|
||||
<meta name="author" content="Vben" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<title></title>
|
||||
<link rel="icon" href="" />
|
||||
<script>
|
||||
(function () {
|
||||
try {
|
||||
var cacheText = window.localStorage.getItem('runtime-setting');
|
||||
var cache = cacheText ? JSON.parse(cacheText) : null;
|
||||
var setting = cache && cache.setting;
|
||||
|
||||
if (!setting) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.__APP_SETTING__ = setting;
|
||||
|
||||
if (setting.appTitle) {
|
||||
document.title = setting.appTitle;
|
||||
}
|
||||
|
||||
if (setting.appIcon) {
|
||||
var icon = document.querySelector('link[rel="icon"]');
|
||||
if (icon) {
|
||||
icon.href = setting.appIcon;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,290 @@
|
||||
<style>
|
||||
html {
|
||||
/* same as ant-design-vue/dist/reset.css setting, avoid the title line-height changed */
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: #f4f7f9;
|
||||
transition: background-color 0.4s ease;
|
||||
|
||||
/* transition: all 0.8s ease-out; */
|
||||
}
|
||||
|
||||
.loading.hidden {
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: all 0.8s ease-out;
|
||||
}
|
||||
|
||||
.dark .loading {
|
||||
background: #0d0d10;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 66px;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
color: rgb(0 0 0 / 85%);
|
||||
}
|
||||
|
||||
.dark .title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: relative;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.loader::before {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 0;
|
||||
width: 48px;
|
||||
height: 5px;
|
||||
content: '';
|
||||
background: hsl(var(--primary, 210 100% 50%) / 50%);
|
||||
border-radius: 50%;
|
||||
animation: shadow-ani 0.5s linear infinite;
|
||||
}
|
||||
|
||||
.loader::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: '';
|
||||
background: hsl(var(--primary, 210 100% 50%));
|
||||
border-radius: 4px;
|
||||
animation: jump-ani 0.5s linear infinite;
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
position: relative;
|
||||
min-width: 420px;
|
||||
min-height: 88px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title,
|
||||
.status-text,
|
||||
.status-subtitle {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
transform: translateX(-50%);
|
||||
transition:
|
||||
opacity 0.45s ease,
|
||||
transform 0.45s ease;
|
||||
}
|
||||
|
||||
.title {
|
||||
top: 0;
|
||||
margin-top: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: rgb(0 0 0 / 85%);
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(10px);
|
||||
}
|
||||
|
||||
.status-text {
|
||||
top: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: rgb(0 0 0 / 85%);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.status-subtitle {
|
||||
top: 48px;
|
||||
font-size: 13px;
|
||||
letter-spacing: 0.08em;
|
||||
color: rgb(100 116 139 / 88%);
|
||||
}
|
||||
|
||||
.title-wrap.is-switching .status-text,
|
||||
.title-wrap.is-switching .status-subtitle {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(8px);
|
||||
}
|
||||
|
||||
.loading.app-title-ready .status-text,
|
||||
.loading.app-title-ready .status-subtitle {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(-10px);
|
||||
}
|
||||
|
||||
.loading.app-title-ready .title {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
|
||||
.dark .status-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dark .status-subtitle {
|
||||
color: rgb(148 163 184 / 78%);
|
||||
}
|
||||
|
||||
@keyframes jump-ani {
|
||||
15% {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: translateY(9px) rotate(22.5deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
border-bottom-right-radius: 40px;
|
||||
transform: translateY(18px) scale(1, 0.9) rotate(45deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translateY(9px) rotate(67.5deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0) rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shadow-ani {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.2, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="loading" id="__app-loading__">
|
||||
<div class="loader" aria-hidden="true"></div>
|
||||
<div class="title-wrap">
|
||||
<div class="status-text" id="__app-loading-status__">正在初始化应用...</div>
|
||||
<div class="status-subtitle" id="__app-loading-subtitle__">
|
||||
请稍候,系统正在准备运行环境
|
||||
</div>
|
||||
<div class="title" id="__app-loading-title__">智联·云</div>
|
||||
</div>
|
||||
</div>
|
||||
<script data-app-loading="runtime-title">
|
||||
(function () {
|
||||
var loadingElement = document.getElementById('__app-loading__');
|
||||
var statusElement = document.getElementById('__app-loading-status__');
|
||||
var subtitleElement = document.getElementById('__app-loading-subtitle__');
|
||||
var titleElement = document.getElementById('__app-loading-title__');
|
||||
var titleWrapElement = titleElement && titleElement.parentElement;
|
||||
var messageTimer = null;
|
||||
var messageIndex = 0;
|
||||
|
||||
var messages = [
|
||||
{
|
||||
status: '正在初始化应用...',
|
||||
subtitle: '请稍候,系统正在准备运行环境',
|
||||
},
|
||||
{
|
||||
status: '正在连接配置中心...',
|
||||
subtitle: '正在读取启动所需的运行时配置',
|
||||
},
|
||||
{
|
||||
status: '正在装载页面资源...',
|
||||
subtitle: '首次加载可能略慢,请稍候片刻',
|
||||
},
|
||||
{
|
||||
status: '正在校准界面状态...',
|
||||
subtitle: '即将进入系统首页',
|
||||
},
|
||||
];
|
||||
|
||||
if (
|
||||
!loadingElement ||
|
||||
!statusElement ||
|
||||
!subtitleElement ||
|
||||
!titleElement ||
|
||||
!titleWrapElement
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
function applyMessage(message) {
|
||||
statusElement.textContent = message.status;
|
||||
subtitleElement.textContent = message.subtitle;
|
||||
}
|
||||
|
||||
function switchMessage(message) {
|
||||
titleWrapElement.classList.add('is-switching');
|
||||
window.setTimeout(function () {
|
||||
applyMessage(message);
|
||||
titleWrapElement.classList.remove('is-switching');
|
||||
}, 220);
|
||||
}
|
||||
|
||||
function startMessageLoop() {
|
||||
statusElement.style.opacity = '';
|
||||
subtitleElement.style.opacity = '';
|
||||
applyMessage(messages[0]);
|
||||
messageTimer = window.setInterval(function () {
|
||||
messageIndex = (messageIndex + 1) % messages.length;
|
||||
switchMessage(messages[messageIndex]);
|
||||
}, 1800);
|
||||
}
|
||||
|
||||
function stopMessageLoop() {
|
||||
if (messageTimer !== null) {
|
||||
window.clearInterval(messageTimer);
|
||||
messageTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function applyTitle(setting) {
|
||||
var appTitle = setting && setting.appTitle;
|
||||
|
||||
if (appTitle) {
|
||||
stopMessageLoop();
|
||||
titleElement.textContent = appTitle;
|
||||
loadingElement.classList.add('app-title-ready');
|
||||
}
|
||||
}
|
||||
|
||||
// 配置已就绪,直接展示标题
|
||||
if (window.__APP_SETTING__) {
|
||||
applyTitle(window.__APP_SETTING__);
|
||||
return;
|
||||
}
|
||||
|
||||
// 配置未就绪,直接展示默认加载文案
|
||||
startMessageLoop();
|
||||
|
||||
// 等待配置返回后,若已启动文案轮播则停止,并展示标题
|
||||
if (window.__APP_SETTING_PROMISE__) {
|
||||
window.__APP_SETTING_PROMISE__
|
||||
.then(function (setting) {
|
||||
applyTitle(setting);
|
||||
})
|
||||
.catch(function () {});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@vben/web-antd",
|
||||
"version": "5.5.9",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
||||
"directory": "apps/web-antd"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "vben",
|
||||
"email": "xxx@example.com",
|
||||
"url": "https://github.com/anncwb"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm vite build --mode production",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": "./src/*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@highlightjs/vue-plugin": "^2.1.0",
|
||||
"@tinymce/tinymce-vue": "^6.1.0",
|
||||
"@vben/access": "workspace:*",
|
||||
"@vben/common-ui": "workspace:*",
|
||||
"@vben/constants": "workspace:*",
|
||||
"@vben/hooks": "workspace:*",
|
||||
"@vben/icons": "workspace:*",
|
||||
"@vben/layouts": "workspace:*",
|
||||
"@vben/locales": "workspace:*",
|
||||
"@vben/plugins": "workspace:*",
|
||||
"@vben/preferences": "workspace:*",
|
||||
"@vben/request": "workspace:*",
|
||||
"@vben/stores": "workspace:*",
|
||||
"@vben/styles": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vben/utils": "workspace:*",
|
||||
"@vueuse/core": "catalog:",
|
||||
"ant-design-vue": "catalog:",
|
||||
"cropperjs": "^1.6.2",
|
||||
"dayjs": "catalog:",
|
||||
"highlight.js": "^11.11.1",
|
||||
"js-md5": "^0.8.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"pinia": "catalog:",
|
||||
"tinymce": "^7.3.0",
|
||||
"vue": "catalog:",
|
||||
"vue-router": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
import type { IncomingMessage, ServerResponse } from 'node:http';
|
||||
import type { PluginOption } from 'vite';
|
||||
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { constants as fsConstants } from 'node:fs';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
interface ApiTypeGeneratorOptions {
|
||||
apiRoot: string;
|
||||
}
|
||||
|
||||
interface DirNode {
|
||||
children?: DirNode[];
|
||||
key: string;
|
||||
title: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface WriteTypePayload {
|
||||
autoImport?: boolean;
|
||||
content?: string;
|
||||
dir?: string;
|
||||
fileName?: string;
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
interface CheckTypeFilePayload {
|
||||
items?: CheckTypeFileItem[];
|
||||
}
|
||||
|
||||
interface CheckTypeFileItem {
|
||||
dir?: string;
|
||||
fileName?: string;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
const API_TYPE_GENERATOR_PREFIX = '/__api-type-generator__';
|
||||
|
||||
export function apiTypeGeneratorPlugin(
|
||||
options: ApiTypeGeneratorOptions,
|
||||
): PluginOption {
|
||||
const apiRoot = path.resolve(options.apiRoot);
|
||||
|
||||
return {
|
||||
apply: 'serve',
|
||||
configureServer(server) {
|
||||
server.middlewares.use(async (request, response, next) => {
|
||||
const url = request.url?.split('?')[0] ?? '';
|
||||
|
||||
if (!url.startsWith(API_TYPE_GENERATOR_PREFIX)) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (
|
||||
request.method === 'GET' &&
|
||||
url === `${API_TYPE_GENERATOR_PREFIX}/dirs`
|
||||
) {
|
||||
const data = await scanApiDirs(apiRoot);
|
||||
|
||||
sendJson(response, 200, { data, success: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
request.method === 'POST' &&
|
||||
url === `${API_TYPE_GENERATOR_PREFIX}/exists`
|
||||
) {
|
||||
const payload = await readJsonBody<CheckTypeFilePayload>(request);
|
||||
const data = await checkTypeFiles(apiRoot, payload);
|
||||
|
||||
sendJson(response, 200, { data, success: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
request.method === 'POST' &&
|
||||
url === `${API_TYPE_GENERATOR_PREFIX}/write`
|
||||
) {
|
||||
const payload = await readJsonBody<WriteTypePayload>(request);
|
||||
const data = await writeTypeFile(apiRoot, payload);
|
||||
|
||||
sendJson(response, 200, { data, success: true });
|
||||
return;
|
||||
}
|
||||
|
||||
sendJson(response, 404, {
|
||||
message: '接口不存在',
|
||||
success: false,
|
||||
});
|
||||
} catch (error) {
|
||||
const statusCode =
|
||||
error instanceof ApiTypeGeneratorError ? error.status : 500;
|
||||
|
||||
sendJson(response, statusCode, {
|
||||
code:
|
||||
error instanceof ApiTypeGeneratorError ? error.code : 'UNKNOWN',
|
||||
message: error instanceof Error ? error.message : '生成失败',
|
||||
success: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
name: 'web-antd:api-type-generator',
|
||||
};
|
||||
}
|
||||
|
||||
class ApiTypeGeneratorError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public status = 400,
|
||||
public code = 'BAD_REQUEST',
|
||||
) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
async function accessFile(filePath: string) {
|
||||
try {
|
||||
await fs.access(filePath, fsConstants.F_OK);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureInApiRoot(apiRoot: string, targetPath: string) {
|
||||
const relativePath = path.relative(apiRoot, targetPath);
|
||||
|
||||
if (
|
||||
relativePath.startsWith('..') ||
|
||||
path.isAbsolute(relativePath) ||
|
||||
relativePath === ''
|
||||
) {
|
||||
if (relativePath === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ApiTypeGeneratorError('目标路径不在 src/api 目录下');
|
||||
}
|
||||
}
|
||||
|
||||
function extractTypeNames(content: string) {
|
||||
const names = new Set<string>();
|
||||
const regex = /export\s+(?:interface|type)\s+([A-Za-z_$][\w$]*)/g;
|
||||
const results = content.matchAll(regex);
|
||||
|
||||
for (const result of results) {
|
||||
const typeName = result[1];
|
||||
|
||||
if (!/(?:Param|Res)$/u.test(typeName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
names.add(typeName);
|
||||
}
|
||||
|
||||
return [...names];
|
||||
}
|
||||
|
||||
function formatTypeImport(typeNames: string[], importPath: string) {
|
||||
const sortedNames = [...new Set(typeNames)].toSorted();
|
||||
|
||||
if (sortedNames.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (sortedNames.length === 1) {
|
||||
return `import type { ${sortedNames[0]} } from '${importPath}';`;
|
||||
}
|
||||
|
||||
return `import type {\n ${sortedNames.join(',\n ')},\n} from '${importPath}';`;
|
||||
}
|
||||
|
||||
function getImportPath(fileName: string) {
|
||||
return `./${fileName.replace(/\.ts$/u, '')}`;
|
||||
}
|
||||
|
||||
function getSafeFileName(fileName?: string) {
|
||||
const safeFileName = fileName?.trim() || 'type.ts';
|
||||
|
||||
if (
|
||||
!/^[\w.-]+\.ts$/u.test(safeFileName) ||
|
||||
safeFileName.includes('..') ||
|
||||
safeFileName.includes('/') ||
|
||||
safeFileName.includes('\\')
|
||||
) {
|
||||
throw new ApiTypeGeneratorError('文件名必须是单个 .ts 文件名');
|
||||
}
|
||||
|
||||
return safeFileName;
|
||||
}
|
||||
|
||||
function getSafeRelativeDir(dir?: string) {
|
||||
const safeDir = (dir ?? '').trim().replaceAll('\\', '/');
|
||||
|
||||
if (!safeDir || safeDir === '.') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (path.isAbsolute(safeDir) || safeDir.split('/').includes('..')) {
|
||||
throw new ApiTypeGeneratorError('目录路径不合法');
|
||||
}
|
||||
|
||||
return safeDir.split('/').filter(Boolean).join('/');
|
||||
}
|
||||
|
||||
function mergeTypeImport(
|
||||
source: string,
|
||||
importPath: string,
|
||||
typeNames: string[],
|
||||
) {
|
||||
const importRegex = new RegExp(
|
||||
String.raw`import\s+type\s+\{([\s\S]*?)\}\s+from\s+['"]${escapeRegExp(
|
||||
importPath,
|
||||
)}['"];?`,
|
||||
'u',
|
||||
);
|
||||
const matchedImport = source.match(importRegex);
|
||||
|
||||
if (matchedImport) {
|
||||
const existedNames = matchedImport[1]
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
const nextImport = formatTypeImport(
|
||||
[...existedNames, ...typeNames],
|
||||
importPath,
|
||||
);
|
||||
|
||||
return source.replace(importRegex, nextImport);
|
||||
}
|
||||
|
||||
const importStatement = formatTypeImport(typeNames, importPath);
|
||||
|
||||
if (!importStatement) {
|
||||
return source;
|
||||
}
|
||||
|
||||
return `${importStatement}\n\n${source}`;
|
||||
}
|
||||
|
||||
function escapeRegExp(value: string) {
|
||||
return value.replaceAll(/[.*+?^${}()|[\]\\]/gu, String.raw`\$&`);
|
||||
}
|
||||
|
||||
async function readJsonBody<T>(request: IncomingMessage) {
|
||||
const chunks: Buffer[] = [];
|
||||
|
||||
for await (const chunk of request) {
|
||||
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
}
|
||||
|
||||
const content = Buffer.concat(chunks).toString('utf8');
|
||||
|
||||
if (!content) {
|
||||
return {} as T;
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(content) as T;
|
||||
} catch {
|
||||
throw new ApiTypeGeneratorError('请求体必须是合法 JSON');
|
||||
}
|
||||
}
|
||||
|
||||
async function scanApiDirs(apiRoot: string) {
|
||||
async function scan(currentDir: string): Promise<DirNode[]> {
|
||||
const dirents = await fs.readdir(currentDir, { withFileTypes: true });
|
||||
const nodes = await Promise.all(
|
||||
dirents
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.toSorted((prev, next) => prev.name.localeCompare(next.name))
|
||||
.map(async (dirent) => {
|
||||
const fullPath = path.join(currentDir, dirent.name);
|
||||
const relativePath = path
|
||||
.relative(apiRoot, fullPath)
|
||||
.replaceAll(path.sep, '/');
|
||||
const children = await scan(fullPath);
|
||||
|
||||
return {
|
||||
children: children.length > 0 ? children : undefined,
|
||||
key: relativePath,
|
||||
title: dirent.name,
|
||||
value: relativePath,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
children: await scan(apiRoot),
|
||||
key: '.',
|
||||
title: 'api',
|
||||
value: '.',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async function checkTypeFiles(
|
||||
apiRoot: string,
|
||||
payload: CheckTypeFilePayload,
|
||||
) {
|
||||
const items = payload.items ?? [];
|
||||
|
||||
if (!Array.isArray(items)) {
|
||||
throw new ApiTypeGeneratorError('检查参数必须是数组');
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
items.map(async (item, index) => {
|
||||
const relativeDir = getSafeRelativeDir(item.dir);
|
||||
const fileName = getSafeFileName(item.fileName);
|
||||
const targetDir = path.resolve(apiRoot, relativeDir);
|
||||
|
||||
ensureInApiRoot(apiRoot, targetDir);
|
||||
|
||||
const targetPath = path.resolve(targetDir, fileName);
|
||||
|
||||
ensureInApiRoot(apiRoot, targetPath);
|
||||
|
||||
return {
|
||||
dir: relativeDir || '.',
|
||||
exists: await accessFile(targetPath),
|
||||
fileName,
|
||||
filePath: path.relative(apiRoot, targetPath).replaceAll(path.sep, '/'),
|
||||
key: item.key ?? String(index),
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function sendJson(response: ServerResponse, statusCode: number, data: unknown) {
|
||||
response.statusCode = statusCode;
|
||||
response.setHeader('Content-Type', 'application/json;charset=utf-8');
|
||||
response.end(JSON.stringify(data));
|
||||
}
|
||||
|
||||
async function updateIndexTypeImport(
|
||||
targetDir: string,
|
||||
fileName: string,
|
||||
content: string,
|
||||
) {
|
||||
const indexPath = path.join(targetDir, 'index.ts');
|
||||
const hasIndexFile = await accessFile(indexPath);
|
||||
|
||||
if (!hasIndexFile) {
|
||||
return {
|
||||
importSkipped: true,
|
||||
importUpdated: false,
|
||||
};
|
||||
}
|
||||
|
||||
const typeNames = extractTypeNames(content);
|
||||
|
||||
if (typeNames.length === 0) {
|
||||
return {
|
||||
importSkipped: true,
|
||||
importUpdated: false,
|
||||
};
|
||||
}
|
||||
|
||||
const source = await fs.readFile(indexPath, 'utf8');
|
||||
const nextSource = mergeTypeImport(
|
||||
source,
|
||||
getImportPath(fileName),
|
||||
typeNames,
|
||||
);
|
||||
|
||||
if (nextSource !== source) {
|
||||
await fs.writeFile(indexPath, nextSource, 'utf8');
|
||||
}
|
||||
|
||||
return {
|
||||
importSkipped: false,
|
||||
importUpdated: nextSource !== source,
|
||||
};
|
||||
}
|
||||
|
||||
async function writeTypeFile(apiRoot: string, payload: WriteTypePayload) {
|
||||
const relativeDir = getSafeRelativeDir(payload.dir);
|
||||
const fileName = getSafeFileName(payload.fileName);
|
||||
const content = payload.content ?? '';
|
||||
|
||||
if (!content.trim()) {
|
||||
throw new ApiTypeGeneratorError('类型定义内容不能为空');
|
||||
}
|
||||
|
||||
const targetDir = path.resolve(apiRoot, relativeDir);
|
||||
|
||||
ensureInApiRoot(apiRoot, targetDir);
|
||||
|
||||
const targetPath = path.resolve(targetDir, fileName);
|
||||
|
||||
ensureInApiRoot(apiRoot, targetPath);
|
||||
|
||||
const exists = await accessFile(targetPath);
|
||||
|
||||
if (exists && !payload.overwrite) {
|
||||
throw new ApiTypeGeneratorError('目标文件已存在', 409, 'FILE_EXISTS');
|
||||
}
|
||||
|
||||
await fs.mkdir(targetDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
targetPath,
|
||||
content.endsWith('\n') ? content : `${content}\n`,
|
||||
'utf8',
|
||||
);
|
||||
|
||||
const importResult = payload.autoImport
|
||||
? await updateIndexTypeImport(targetDir, fileName, content)
|
||||
: {
|
||||
importSkipped: false,
|
||||
importUpdated: false,
|
||||
};
|
||||
|
||||
return {
|
||||
exists,
|
||||
filePath: path.relative(apiRoot, targetPath).replaceAll(path.sep, '/'),
|
||||
...importResult,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from '@vben/tailwind-config/postcss';
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"tDashboard": {
|
||||
"businessAlert": true,
|
||||
"businessVolume": true,
|
||||
"dataSharing": true,
|
||||
"feeSituation": true,
|
||||
"lifeCycle": true,
|
||||
"locationDistribution": true,
|
||||
"myPanel": true,
|
||||
"myPanelNew": true,
|
||||
"myPanelSimActive": true,
|
||||
"myPanelSimCount": true,
|
||||
"myPanelUseData": true,
|
||||
"myPanelUseMsg": true,
|
||||
"quickAccessBorder": true,
|
||||
"trafficPool": true
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"appTitle": "物联网全生命周期管理平台",
|
||||
"appIcon": "/logo.png",
|
||||
"loginPageTitle": "物联网设备上云首选",
|
||||
"loginPageDescription": "新一代物联网设备统一接入平台",
|
||||
"loginSloganImage": "",
|
||||
"copyright": {
|
||||
"companyName": "示例智联",
|
||||
"companySiteLink": "https://example.com",
|
||||
"date": "2024-2025",
|
||||
"icp": "",
|
||||
"icpLink": "https://beian.miit.gov.cn/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
|
||||
/**
|
||||
* Ant Design Vue 基础组件统一在这里异步引入。
|
||||
*
|
||||
* adapter 层只关心组件映射关系,避免把具体 UI 库的 import 细节散落到注册文件中。
|
||||
*/
|
||||
export const AutoComplete = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/auto-complete'),
|
||||
);
|
||||
|
||||
export const Button = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/button'),
|
||||
);
|
||||
|
||||
export const Checkbox = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/checkbox'),
|
||||
);
|
||||
|
||||
export const CheckboxGroup = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup),
|
||||
);
|
||||
|
||||
export const DatePicker = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/date-picker'),
|
||||
);
|
||||
|
||||
export const Divider = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/divider'),
|
||||
);
|
||||
|
||||
export const Image = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/image'),
|
||||
);
|
||||
|
||||
export const Input = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/input'),
|
||||
);
|
||||
|
||||
export const InputNumber = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/input-number'),
|
||||
);
|
||||
|
||||
export const InputPassword = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/input').then((res) => res.InputPassword),
|
||||
);
|
||||
|
||||
export const Mentions = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/mentions'),
|
||||
);
|
||||
|
||||
export const PreviewGroup = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
||||
);
|
||||
|
||||
export const Radio = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/radio'),
|
||||
);
|
||||
|
||||
export const RadioGroup = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/radio').then((res) => res.RadioGroup),
|
||||
);
|
||||
|
||||
export const RangePicker = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/date-picker').then((res) => res.RangePicker),
|
||||
);
|
||||
|
||||
export const Rate = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/rate'),
|
||||
);
|
||||
|
||||
export const Select = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/select'),
|
||||
);
|
||||
|
||||
export const Space = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/space'),
|
||||
);
|
||||
|
||||
export const Switch = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/switch'),
|
||||
);
|
||||
|
||||
export const Textarea = defineAsyncComponent(() =>
|
||||
import('ant-design-vue/es/input').then((res) => res.Textarea),
|
||||
);
|
||||
|
||||
export const TimePicker = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/time-picker'),
|
||||
);
|
||||
|
||||
export const TreeSelect = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/tree-select'),
|
||||
);
|
||||
|
||||
export const Cascader = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/cascader'),
|
||||
);
|
||||
|
||||
export const Upload = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/upload'),
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
import { globalShareState } from '@vben/common-ui';
|
||||
|
||||
import { notification } from 'ant-design-vue';
|
||||
|
||||
/**
|
||||
* 框架共享消息适配。
|
||||
*
|
||||
* common-ui 内部只声明消息场景,这里绑定到当前 UI 库的 notification 实现。
|
||||
*/
|
||||
export function defineComponentAdapterMessage() {
|
||||
globalShareState.defineMessage({
|
||||
copyPreferencesSuccess: (title, content) => {
|
||||
notification.success({
|
||||
description: content,
|
||||
message: title,
|
||||
placement: 'bottomRight',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import type { UploadFile, UploadProps } from 'ant-design-vue';
|
||||
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import { h, render, unref } from 'vue';
|
||||
|
||||
import { Image, PreviewGroup } from '../antd';
|
||||
|
||||
/**
|
||||
* UploadFile 没有稳定的图片标识字段时,通过 url/name/type 组合判断是否走图片预览。
|
||||
*/
|
||||
function isImageFile(file: UploadFile): boolean {
|
||||
const imageExtensions = new Set(['bmp', 'gif', 'jpeg', 'jpg', 'png', 'webp']);
|
||||
|
||||
if (file.url) {
|
||||
const ext = file.url?.split('.').pop()?.toLowerCase();
|
||||
return ext ? imageExtensions.has(ext) : false;
|
||||
}
|
||||
|
||||
if (!file.type) {
|
||||
const ext = file.name?.split('.').pop()?.toLowerCase();
|
||||
return ext ? imageExtensions.has(ext) : false;
|
||||
}
|
||||
|
||||
return file.type.startsWith('image/');
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地待上传图片没有 url 时,需要转成 base64 才能进入 ImagePreviewGroup。
|
||||
*/
|
||||
function getBase64(file: File) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.addEventListener('load', () => resolve(reader.result));
|
||||
reader.addEventListener('error', (error) => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 Ant Design Vue ImagePreviewGroup 创建一次性预览容器。
|
||||
*
|
||||
* 预览关闭后会卸载并移除临时 DOM,避免多次预览后残留节点。
|
||||
*/
|
||||
export const previewImage = async (
|
||||
file: UploadFile,
|
||||
visible: Ref<boolean>,
|
||||
fileList: Ref<UploadProps['fileList']>,
|
||||
) => {
|
||||
// 非图片沿用文件打开行为,不进入图片预览组
|
||||
if (!isImageFile(file)) {
|
||||
if (file.url) {
|
||||
window.open(file.url, '_blank');
|
||||
} else if (file.preview) {
|
||||
window.open(file.preview, '_blank');
|
||||
} else {
|
||||
console.warn('无法打开文件,没有可用的URL或预览地址');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Image 与 PreviewGroup 只有预览时才加载,保持基础表单渲染轻量
|
||||
const [ImageComponent, PreviewGroupComponent] = await Promise.all([
|
||||
Image,
|
||||
PreviewGroup,
|
||||
]);
|
||||
|
||||
const imageFiles = (unref(fileList) || []).filter((element) =>
|
||||
isImageFile(element),
|
||||
);
|
||||
|
||||
// 同一上传列表中的图片都加入预览组,支持左右切换
|
||||
for (const imgFile of imageFiles) {
|
||||
if (!imgFile.url && !imgFile.preview && imgFile.originFileObj) {
|
||||
imgFile.preview = (await getBase64(imgFile.originFileObj)) as string;
|
||||
}
|
||||
}
|
||||
|
||||
const container: HTMLElement | null = document.createElement('div');
|
||||
document.body.append(container);
|
||||
|
||||
// 避免关闭动画期间重复触发卸载
|
||||
let isUnmounted = false;
|
||||
|
||||
const PreviewWrapper = {
|
||||
setup() {
|
||||
return () => {
|
||||
if (isUnmounted) return null;
|
||||
|
||||
return h(
|
||||
PreviewGroupComponent,
|
||||
{
|
||||
class: 'hidden',
|
||||
preview: {
|
||||
visible: visible.value,
|
||||
current: imageFiles.findIndex((f) => f.uid === file.uid),
|
||||
onVisibleChange: (value: boolean) => {
|
||||
visible.value = value;
|
||||
if (!value) {
|
||||
// 等待预览关闭动画结束后再卸载临时容器
|
||||
setTimeout(() => {
|
||||
if (!isUnmounted && container) {
|
||||
isUnmounted = true;
|
||||
render(null, container);
|
||||
container.remove();
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
() =>
|
||||
imageFiles.map((imgFile) =>
|
||||
h(ImageComponent, {
|
||||
key: imgFile.uid,
|
||||
src: imgFile.url || imgFile.preview,
|
||||
}),
|
||||
),
|
||||
);
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
render(h(PreviewWrapper), container);
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { defineComponent, h, ref } from 'vue';
|
||||
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
/**
|
||||
* 为输入类/选择类组件补齐统一占位文案,并保留原组件暴露的方法。
|
||||
*/
|
||||
export const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
return defineComponent({
|
||||
name: component.name,
|
||||
inheritAttrs: false,
|
||||
setup: (props: any, { attrs, expose, slots }) => {
|
||||
const placeholder =
|
||||
props?.placeholder ||
|
||||
attrs?.placeholder ||
|
||||
$t(`ui.placeholder.${type}`);
|
||||
const innerRef = ref();
|
||||
|
||||
// 透传内部组件实例方法,避免包装后影响外部通过 ref 调用 focus 等能力
|
||||
expose(
|
||||
new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (_target, key) => innerRef.value?.[key],
|
||||
has: (_target, key) => key in (innerRef.value || {}),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return () =>
|
||||
h(
|
||||
component,
|
||||
{ ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
|
||||
slots,
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,114 @@
|
||||
import type {
|
||||
UploadChangeParam,
|
||||
UploadFile,
|
||||
UploadProps,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { defineComponent, h, ref, watch } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { Button, Upload } from '../antd';
|
||||
import { previewImage } from './upload-preview';
|
||||
|
||||
/**
|
||||
* Upload 未提供自定义插槽时,补齐项目统一的默认上传按钮。
|
||||
*/
|
||||
function createDefaultSlotsWithUpload(listType: string, placeholder: string) {
|
||||
switch (listType) {
|
||||
case 'picture-card': {
|
||||
return {
|
||||
default: () => placeholder,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
return {
|
||||
default: () =>
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
icon: h(IconifyIcon, {
|
||||
icon: 'ant-design:upload-outlined',
|
||||
class: 'mb-1 size-4',
|
||||
}),
|
||||
},
|
||||
() => placeholder,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 适配 Ant Design Vue Upload 到 Vben Form:
|
||||
* - 使用 modelValue 与表单值同步
|
||||
* - 上传列表为空时回写 undefined
|
||||
* - 内置图片预览,非图片文件直接打开地址
|
||||
*/
|
||||
export const withPreviewUpload = () => {
|
||||
return defineComponent({
|
||||
name: Upload.name,
|
||||
emits: ['change', 'update:modelValue'],
|
||||
setup: (
|
||||
props: any,
|
||||
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
|
||||
) => {
|
||||
const previewVisible = ref<boolean>(false);
|
||||
const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`);
|
||||
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
|
||||
const fileList = ref<UploadProps['fileList']>(
|
||||
attrs?.fileList || attrs?.['file-list'] || [],
|
||||
);
|
||||
|
||||
const handleChange = async (event: UploadChangeParam) => {
|
||||
fileList.value = event.fileList;
|
||||
emit('change', event);
|
||||
emit(
|
||||
'update:modelValue',
|
||||
event.fileList?.length ? fileList.value : undefined,
|
||||
);
|
||||
};
|
||||
|
||||
const handlePreview = async (file: UploadFile) => {
|
||||
previewVisible.value = true;
|
||||
await previewImage(file, previewVisible, fileList);
|
||||
};
|
||||
|
||||
const renderUploadButton = (): any => {
|
||||
const isDisabled = attrs.disabled;
|
||||
|
||||
// 禁用状态下只展示文件列表,不再渲染上传入口
|
||||
if (isDisabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return isEmpty(slots)
|
||||
? createDefaultSlotsWithUpload(listType, placeholder)
|
||||
: slots;
|
||||
};
|
||||
|
||||
// 监听 formApi.setValues 等外部回填,保持 Upload 内部 fileList 同步
|
||||
watch(
|
||||
() => attrs.modelValue,
|
||||
(res) => {
|
||||
fileList.value = res;
|
||||
},
|
||||
);
|
||||
|
||||
return () =>
|
||||
h(
|
||||
Upload,
|
||||
{
|
||||
...props,
|
||||
...attrs,
|
||||
fileList: fileList.value,
|
||||
onChange: handleChange,
|
||||
onPreview: handlePreview,
|
||||
},
|
||||
renderUploadButton(),
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,136 @@
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import type { ComponentType } from './types';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
|
||||
|
||||
import { HtcRegisterComponent } from '#/components/HtCustom/FormExpand/register';
|
||||
import { Tinymce as RichTextarea } from '#/components/tinymce';
|
||||
import { FileUpload, ImageUpload } from '#/components/upload';
|
||||
|
||||
import {
|
||||
AutoComplete,
|
||||
Button,
|
||||
Cascader,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
DatePicker,
|
||||
Divider,
|
||||
Input,
|
||||
InputNumber,
|
||||
InputPassword,
|
||||
Mentions,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
RangePicker,
|
||||
Rate,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Textarea,
|
||||
TimePicker,
|
||||
TreeSelect,
|
||||
} from './antd';
|
||||
import { defineComponentAdapterMessage } from './helpers/message';
|
||||
import { withDefaultPlaceholder } from './helpers/with-default-placeholder';
|
||||
import { withPreviewUpload } from './helpers/with-preview-upload';
|
||||
|
||||
/**
|
||||
* 通用组件适配层。
|
||||
*
|
||||
* 这里只维护“组件名称 -> 真实组件”的映射关系,供 vben-form、vben-modal、
|
||||
* vben-drawer 等框架组件通过 globalShareState 复用。
|
||||
*/
|
||||
function createComponentAdapterMap(): Partial<
|
||||
Record<ComponentType, Component>
|
||||
> {
|
||||
return {
|
||||
// 如果你的组件体积比较大,可以使用异步加载
|
||||
// Button: () =>
|
||||
// import('xxx').then((res) => res.Button),
|
||||
ApiCascader: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||
component: Cascader,
|
||||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
}),
|
||||
ApiSelect: withDefaultPlaceholder(
|
||||
{
|
||||
...ApiComponent,
|
||||
name: 'ApiSelect',
|
||||
},
|
||||
'select',
|
||||
{
|
||||
component: Select,
|
||||
loadingSlot: 'suffixIcon',
|
||||
visibleEvent: 'onDropdownVisibleChange',
|
||||
modelPropName: 'value',
|
||||
},
|
||||
),
|
||||
ApiTreeSelect: withDefaultPlaceholder(
|
||||
{
|
||||
...ApiComponent,
|
||||
name: 'ApiTreeSelect',
|
||||
},
|
||||
'select',
|
||||
{
|
||||
component: TreeSelect,
|
||||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
optionsPropName: 'treeData',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
},
|
||||
),
|
||||
AutoComplete,
|
||||
Cascader,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
DatePicker,
|
||||
// 弹窗、抽屉等框架组件会通过共享状态读取这两个按钮组件
|
||||
DefaultButton: (props, { attrs, slots }) => {
|
||||
return h(Button, { ...props, attrs, type: 'default' }, slots);
|
||||
},
|
||||
Divider,
|
||||
FileUpload,
|
||||
ImageUpload,
|
||||
IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
|
||||
iconSlot: 'addonAfter',
|
||||
inputComponent: Input,
|
||||
modelValueProp: 'value',
|
||||
}),
|
||||
Input: withDefaultPlaceholder(Input, 'input'),
|
||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||
PrimaryButton: (props, { attrs, slots }) => {
|
||||
return h(Button, { ...props, attrs, type: 'primary' }, slots);
|
||||
},
|
||||
Radio,
|
||||
RadioGroup,
|
||||
RangePicker,
|
||||
Rate,
|
||||
RichTextarea,
|
||||
Select: withDefaultPlaceholder(Select, 'select'),
|
||||
// SelectDivision,
|
||||
Space,
|
||||
Switch,
|
||||
Textarea: withDefaultPlaceholder(Textarea, 'input'),
|
||||
TimePicker,
|
||||
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
|
||||
Upload: withPreviewUpload(),
|
||||
...HtcRegisterComponent,
|
||||
};
|
||||
}
|
||||
|
||||
async function initComponentAdapter() {
|
||||
// 先注册组件,再初始化 form 适配,确保 setupVbenForm 能读到完整组件表
|
||||
globalShareState.setComponents(createComponentAdapterMap());
|
||||
defineComponentAdapterMessage();
|
||||
}
|
||||
|
||||
export { initComponentAdapter };
|
||||
export type { ComponentType };
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { SchemaComponentType } from './types';
|
||||
|
||||
import type { HtcComponentPropsMap } from '#/components/HtCustom/FormExpand/register';
|
||||
|
||||
type ComponentPropsGetter<Props> = (
|
||||
value: Partial<Record<string, any>>,
|
||||
actions: any,
|
||||
) => Props;
|
||||
|
||||
type ComponentPropsMap = HtcComponentPropsMap;
|
||||
|
||||
type UntypedComponentProps =
|
||||
| ComponentPropsGetter<Record<string, any>>
|
||||
| Record<string, any>;
|
||||
|
||||
export type ComponentProps<T extends SchemaComponentType> =
|
||||
T extends keyof ComponentPropsMap
|
||||
? ComponentPropsGetter<ComponentPropsMap[T]> | ComponentPropsMap[T]
|
||||
: UntypedComponentProps;
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { BaseFormComponentType } from '@vben/common-ui';
|
||||
|
||||
import type { HtcRegisterComponentName } from '#/components/HtCustom/FormExpand/register';
|
||||
|
||||
/**
|
||||
* 表单 schema 中 component 字段允许使用的组件名称。
|
||||
*
|
||||
* 新增适配组件时,需要同时在这里补充名称,并在 index.ts 中注册真实组件。
|
||||
*/
|
||||
export type AdapterComponentType =
|
||||
| 'ApiCascader'
|
||||
| 'ApiSelect'
|
||||
| 'ApiTreeSelect'
|
||||
| 'AutoComplete'
|
||||
| 'Cascader'
|
||||
| 'Checkbox'
|
||||
| 'CheckboxGroup'
|
||||
| 'DatePicker'
|
||||
| 'DefaultButton'
|
||||
| 'Divider'
|
||||
| 'FileUpload'
|
||||
| 'HtcFormSwitch'
|
||||
| 'IconPicker'
|
||||
| 'ImageUpload'
|
||||
| 'Input'
|
||||
| 'InputNumber'
|
||||
| 'InputPassword'
|
||||
| 'Mentions'
|
||||
| 'PrimaryButton'
|
||||
| 'Radio'
|
||||
| 'RadioGroup'
|
||||
| 'RangePicker'
|
||||
| 'Rate'
|
||||
| 'RichTextarea'
|
||||
| 'Select'
|
||||
| 'SelectDivision'
|
||||
| 'Space'
|
||||
| 'Switch'
|
||||
| 'Textarea'
|
||||
| 'TimePicker'
|
||||
| 'TreeSelect'
|
||||
| 'Upload';
|
||||
|
||||
export type BaseComponentType =
|
||||
| 'DefaultButton'
|
||||
| 'PrimaryButton'
|
||||
| 'VbenCheckbox'
|
||||
| 'VbenInput'
|
||||
| 'VbenInputPassword'
|
||||
| 'VbenPinInput'
|
||||
| 'VbenSelect';
|
||||
|
||||
export type SchemaComponentType =
|
||||
| AdapterComponentType
|
||||
| BaseComponentType
|
||||
| HtcRegisterComponentName;
|
||||
|
||||
export type ComponentType =
|
||||
| AdapterComponentType
|
||||
| BaseFormComponentType
|
||||
| HtcRegisterComponentName;
|
||||
@@ -0,0 +1,68 @@
|
||||
import type {
|
||||
VbenFormProps as BaseVbenFormProps,
|
||||
VbenFormSchema as FormSchema,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { ComponentProps } from './component/props';
|
||||
import type { SchemaComponentType } from './component/types';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
async function initSetupVbenForm() {
|
||||
setupVbenForm<ComponentType>({
|
||||
config: {
|
||||
// ant design vue组件库默认都是 v-model:value
|
||||
baseModelPropName: 'value',
|
||||
|
||||
// 一些组件是 v-model:checked 或者 v-model:fileList
|
||||
modelPropNameMap: {
|
||||
Checkbox: 'checked',
|
||||
Radio: 'checked',
|
||||
RichTextarea: 'modelValue',
|
||||
Switch: 'checked',
|
||||
Upload: 'fileList',
|
||||
ImageUpload: 'value',
|
||||
},
|
||||
},
|
||||
defineRules: {
|
||||
// 输入项目必填国际化适配
|
||||
required: (value, _params, ctx) => {
|
||||
if (value === undefined || value === null || value.length === 0) {
|
||||
return $t('ui.formRules.required', [ctx.label]);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 选择项目必填国际化适配
|
||||
selectRequired: (value, _params, ctx) => {
|
||||
if (value === undefined || value === null) {
|
||||
return $t('ui.formRules.selectRequired', [ctx.label]);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
type TypedFormSchema<T extends SchemaComponentType> = Omit<
|
||||
FormSchema<T>,
|
||||
'component' | 'componentProps'
|
||||
> & {
|
||||
component: T;
|
||||
componentProps?: ComponentProps<T>;
|
||||
};
|
||||
|
||||
export type VbenFormSchema = {
|
||||
[K in SchemaComponentType]: TypedFormSchema<K>;
|
||||
}[SchemaComponentType];
|
||||
|
||||
export type VbenFormProps = Omit<BaseVbenFormProps<ComponentType>, 'schema'> & {
|
||||
schema?: VbenFormSchema[];
|
||||
};
|
||||
|
||||
const useVbenForm = (options: VbenFormProps) => {
|
||||
return useForm<ComponentType>(options as BaseVbenFormProps<ComponentType>);
|
||||
};
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
@@ -0,0 +1,124 @@
|
||||
/* eslint-disable vue/no-side-effects-in-computed-properties */
|
||||
import { computed, defineComponent, h, ref, watch } from 'vue';
|
||||
|
||||
import hljs from 'highlight.js/lib/core';
|
||||
|
||||
const component = defineComponent({
|
||||
props: {
|
||||
code: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
autodetect: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
ignoreIllegals: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const language = ref(props.language);
|
||||
const ignoreIllegals = ref(props.ignoreIllegals);
|
||||
watch(
|
||||
() => props.language,
|
||||
(newLanguage) => {
|
||||
language.value = newLanguage;
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => props.ignoreIllegals,
|
||||
(newIgnoreIllegals) => {
|
||||
ignoreIllegals.value = newIgnoreIllegals;
|
||||
},
|
||||
);
|
||||
|
||||
const autodetect = computed(() => props.autodetect || !language.value);
|
||||
const cannotDetectLanguage = computed(
|
||||
() => !autodetect.value && !hljs.getLanguage(language.value),
|
||||
);
|
||||
|
||||
const className = computed((): string => {
|
||||
return cannotDetectLanguage.value ? '' : `hljs ${language.value}`;
|
||||
});
|
||||
|
||||
const highlightedCode = computed((): string => {
|
||||
// No idea what language to use, return raw code
|
||||
if (cannotDetectLanguage.value) {
|
||||
console.warn(
|
||||
`The language "${language.value}" you specified could not be found.`,
|
||||
);
|
||||
return props.code;
|
||||
}
|
||||
|
||||
if (autodetect.value) {
|
||||
const result = hljs.highlightAuto(props.code);
|
||||
language.value = result.language ?? '';
|
||||
return result.value;
|
||||
} else {
|
||||
const result = hljs.highlight(props.code, {
|
||||
language: language.value,
|
||||
ignoreIllegals: props.ignoreIllegals,
|
||||
});
|
||||
return result.value;
|
||||
}
|
||||
});
|
||||
// const saveSelection = (e: any) => {
|
||||
// const selection = window.getSelection();
|
||||
// if (selection && selection.rangeCount && selection.rangeCount > 0) {
|
||||
// const range = selection.getRangeAt(0);
|
||||
// return range;
|
||||
// }
|
||||
// return null;
|
||||
// };
|
||||
// const restoreSelection = (range: any, el: any) => {
|
||||
// if (range) {
|
||||
// const selection = window.getSelection();
|
||||
// if (selection) {
|
||||
// selection.removeAllRanges();
|
||||
// selection.addRange(range);
|
||||
// console.log('selection range', range);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
const updateContent = (e: any) => {
|
||||
// const range = saveSelection(e)
|
||||
const result = hljs.highlight(e.target.innerText, {
|
||||
language: language.value,
|
||||
ignoreIllegals: props.ignoreIllegals,
|
||||
});
|
||||
e.target.innerHTML = result.value;
|
||||
emit('update:code', e.target.innerText);
|
||||
// setTimeout(() => {
|
||||
// restoreSelection(range, e.target)
|
||||
// }, 0)
|
||||
};
|
||||
return {
|
||||
className,
|
||||
highlightedCode,
|
||||
updateContent,
|
||||
emit,
|
||||
};
|
||||
},
|
||||
render() {
|
||||
const updateContent = this.updateContent;
|
||||
return h('pre', {}, [
|
||||
h('code', {
|
||||
class: this.className,
|
||||
innerHTML: this.highlightedCode,
|
||||
contenteditable: true,
|
||||
// onInput(e: any) {},
|
||||
onBlur(e: any) {
|
||||
updateContent(e);
|
||||
},
|
||||
}),
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
export default component;
|
||||
@@ -0,0 +1,69 @@
|
||||
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
import { useVbenForm } from '@vben/common-ui';
|
||||
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||
|
||||
import { Button, Image } from 'ant-design-vue';
|
||||
|
||||
setupVbenVxeTable({
|
||||
configVxeTable: (vxeUI) => {
|
||||
vxeUI.setConfig({
|
||||
grid: {
|
||||
align: 'center',
|
||||
border: false,
|
||||
columnConfig: {
|
||||
resizable: true,
|
||||
},
|
||||
minHeight: 180,
|
||||
formConfig: {
|
||||
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||
enabled: false,
|
||||
},
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
response: {
|
||||
result: 'items',
|
||||
total: 'total',
|
||||
list: 'items',
|
||||
},
|
||||
showActiveMsg: true,
|
||||
showResponseMsg: false,
|
||||
},
|
||||
round: true,
|
||||
showOverflow: true,
|
||||
size: 'small',
|
||||
} as VxeTableGridOptions,
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderTableDefault(renderOpts, params) {
|
||||
const { props } = renderOpts;
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field], ...props });
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
{ size: 'small', type: 'link' },
|
||||
{ default: () => props?.text },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||
// vxeUI.formats.add
|
||||
},
|
||||
useVbenForm,
|
||||
});
|
||||
|
||||
export { useVbenVxeGrid };
|
||||
|
||||
export type * from '@vben/plugins/vxe-table';
|
||||
@@ -0,0 +1,207 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export interface AgentDept {
|
||||
deptId: number;
|
||||
tenantId?: string;
|
||||
deptType: number;
|
||||
parentId: number;
|
||||
ancestors?: string;
|
||||
deptKey?: string;
|
||||
deptName: string;
|
||||
deptCategory?: string;
|
||||
orderNum?: number;
|
||||
leader?: number;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
status: string;
|
||||
creditCode?: string;
|
||||
areaCode?: string;
|
||||
address?: string;
|
||||
deptRole?: number;
|
||||
userName?: string;
|
||||
defaultUserName?: string;
|
||||
nickName?: string;
|
||||
defaultNickName?: string;
|
||||
defaultUserNickName?: string;
|
||||
defaultUserId?: number;
|
||||
password?: string;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export interface AgentRole {
|
||||
roleId: number;
|
||||
tenantId?: string;
|
||||
deptId: number;
|
||||
deptName?: string;
|
||||
roleName: string;
|
||||
roleKey: string;
|
||||
roleSort?: number;
|
||||
dataScope?: string;
|
||||
menuCheckStrictly?: number;
|
||||
deptCheckStrictly?: number;
|
||||
isPass?: number;
|
||||
sourceRoleId?: number;
|
||||
sourceDeptId?: number;
|
||||
status: string;
|
||||
createdAt?: string;
|
||||
remark?: string;
|
||||
isDefaultRole?: boolean;
|
||||
}
|
||||
|
||||
export interface MenuTreeItem {
|
||||
title: string;
|
||||
key: string;
|
||||
parentId: number;
|
||||
menuId: number;
|
||||
menuName: string;
|
||||
menuType: string;
|
||||
perms?: string;
|
||||
children?: MenuTreeItem[];
|
||||
}
|
||||
|
||||
export interface AgentRoleView extends AgentRole {
|
||||
isTemplateRole: boolean;
|
||||
isDeptDefaultRole: boolean;
|
||||
menuIds: number[];
|
||||
deptIds: number[];
|
||||
allowedMenuIds: number[];
|
||||
menuTree: MenuTreeItem[];
|
||||
}
|
||||
|
||||
export interface AgentUser {
|
||||
userId: number;
|
||||
tenantId: string;
|
||||
deptId: number;
|
||||
userName: string;
|
||||
nickName: string;
|
||||
userType: string;
|
||||
email: string;
|
||||
phonenumber: string;
|
||||
sex: string;
|
||||
avatar: string;
|
||||
status: string;
|
||||
loginIp?: string;
|
||||
loginDate?: string;
|
||||
createdDept?: number;
|
||||
createdBy?: number;
|
||||
createdAt?: string;
|
||||
remark?: string;
|
||||
deptInfo?: { deptId: number; deptName: string };
|
||||
roles?: AgentRole[];
|
||||
isDefaultUser?: boolean;
|
||||
}
|
||||
|
||||
export interface AgentDeptListParams {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
deptName?: string;
|
||||
status?: string;
|
||||
deptType?: number;
|
||||
}
|
||||
|
||||
export function exportAgentDeptApi(params?: Record<string, unknown>) {
|
||||
return requestClient.get<Blob>('/agent/dept/export', {
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function exportAgentUserApi(params?: Record<string, unknown>) {
|
||||
return requestClient.get<Blob>('/agent/user/export', {
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function getAgentDeptListApi(params?: AgentDeptListParams) {
|
||||
return requestClient.get<{
|
||||
items: AgentDept[];
|
||||
page: number;
|
||||
pageSize: number;
|
||||
total: number;
|
||||
}>('/agent/dept/list', { params });
|
||||
}
|
||||
|
||||
export function getAgentDeptViewApi(params: { deptId: number }) {
|
||||
return requestClient.get<AgentDept>('/agent/dept/view', { params });
|
||||
}
|
||||
|
||||
export function saveAgentDeptApi(params: Partial<AgentDept>) {
|
||||
return requestClient.post<{ deptId: number }>('/agent/dept/save', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteAgentDeptApi(params: { deptId: number }) {
|
||||
return requestClient.post('/agent/dept/delete', { ...params });
|
||||
}
|
||||
|
||||
export function resetAgentDeptPasswordApi(params: {
|
||||
deptId: number;
|
||||
password: string;
|
||||
}) {
|
||||
return requestClient.post('/agent/dept/resetPassword', { ...params });
|
||||
}
|
||||
|
||||
export function getAgentUserListApi(params?: Record<string, any>) {
|
||||
return requestClient.get<{ items: AgentUser[]; total: number }>(
|
||||
'/agent/user/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
export function getAgentUserViewApi(params: { userId: number }) {
|
||||
return requestClient.get<AgentUser>('/agent/user/view', { params });
|
||||
}
|
||||
|
||||
export function addAgentUserApi(params: Record<string, any>) {
|
||||
return requestClient.post('/agent/user/add', { ...params });
|
||||
}
|
||||
|
||||
export function updateAgentUserApi(params: Record<string, any>) {
|
||||
return requestClient.post('/agent/user/update', { ...params });
|
||||
}
|
||||
|
||||
export function deleteAgentUserApi(params: {
|
||||
userId?: number;
|
||||
userIds?: number[];
|
||||
}) {
|
||||
return requestClient.post('/agent/user/delete', { ...params });
|
||||
}
|
||||
|
||||
export function resetAgentUserPasswordApi(params: {
|
||||
password: string;
|
||||
userId: number;
|
||||
}) {
|
||||
return requestClient.post('/agent/user/resetPassword', { ...params });
|
||||
}
|
||||
|
||||
export function getAgentRoleListApi(params?: Record<string, any>) {
|
||||
return requestClient.get<{ items: AgentRole[]; total: number }>(
|
||||
'/agent/role/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
export function getAgentRoleViewApi(params: { roleId: number }) {
|
||||
return requestClient.get<AgentRoleView>('/agent/role/view', { params });
|
||||
}
|
||||
|
||||
export function saveAgentRoleApi(params: Record<string, any>) {
|
||||
return requestClient.post<{ roleId: number }>('/agent/role/save', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteAgentRoleApi(params: {
|
||||
roleId?: number;
|
||||
roleIds?: number[];
|
||||
}) {
|
||||
return requestClient.post('/agent/role/delete', { ...params });
|
||||
}
|
||||
|
||||
export function getAgentMenuTreeApi() {
|
||||
return requestClient.get<{ items: MenuTreeItem[]; menuIds: number[] }>(
|
||||
'/agent/menu/tree',
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取开放接口权限组表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('agent/tApiGroup/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除开放接口权限组表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('agent/tApiGroup/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑开放接口权限组表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('agent/tApiGroup/edit', { ...params });
|
||||
}
|
||||
|
||||
// 修改开放接口权限组表状态
|
||||
export function Status(params:any) {
|
||||
return requestClient.post<any>('agent/tApiGroup/status', { ...params });
|
||||
}
|
||||
|
||||
// 获取开放接口权限组表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('agent/tApiGroup/view', { params });
|
||||
}
|
||||
|
||||
// 导出开放接口权限组表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/agent/tApiGroup/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取开放接口资源表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('agent/tApiResource/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除开放接口资源表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('agent/tApiResource/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑开放接口资源表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('agent/tApiResource/edit', { ...params });
|
||||
}
|
||||
|
||||
// 修改开放接口资源表状态
|
||||
export function Status(params:any) {
|
||||
return requestClient.post<any>('agent/tApiResource/status', { ...params });
|
||||
}
|
||||
|
||||
// 获取开放接口资源表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('agent/tApiResource/view', { params });
|
||||
}
|
||||
|
||||
// 导出开放接口资源表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/agent/tApiResource/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export interface DownloadCenterListParam {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
keyword?: string;
|
||||
bizKey?: string;
|
||||
/** 多个状态用逗号分隔:0排队 2生成中 1已完成 3失败 */
|
||||
status?: string;
|
||||
createdAt?: string[];
|
||||
}
|
||||
|
||||
export interface DownloadCenterItem {
|
||||
id: number;
|
||||
taskNo: string;
|
||||
bizKey: string;
|
||||
bizName: string;
|
||||
status: number;
|
||||
totalCount: number;
|
||||
fileName: string;
|
||||
fileSize: number;
|
||||
errorMessage?: string;
|
||||
createdAt?: string;
|
||||
finishTime?: string;
|
||||
expireTime?: string;
|
||||
deletedTime?: null | string;
|
||||
deleteReason?: '' | 'expired' | 'user';
|
||||
}
|
||||
|
||||
export interface DownloadCenterListResult {
|
||||
items: DownloadCenterItem[];
|
||||
page: number;
|
||||
pageSize: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface DownloadCenterRecentResult {
|
||||
items: DownloadCenterItem[];
|
||||
runningCount: number;
|
||||
finishedCount: number;
|
||||
}
|
||||
|
||||
/** 下载中心列表 */
|
||||
export function List(params: DownloadCenterListParam) {
|
||||
return requestClient.get<DownloadCenterListResult>(
|
||||
'/common/downloadCenter/list',
|
||||
{
|
||||
params,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 右上角入口:最近任务与进行中数量。
|
||||
* 这是辅助信息,无权限或后端未就绪时静默失败,不能弹全局错误打扰用户。 */
|
||||
export function Recent(limit = 5) {
|
||||
return requestClient.get<DownloadCenterRecentResult>(
|
||||
'/common/downloadCenter/recent',
|
||||
{ params: { limit }, errorMessageMode: 'none' },
|
||||
);
|
||||
}
|
||||
|
||||
/** 下载导出文件:业务错误可能以 HTTP 200 JSON Blob 返回,不能当作 xlsx 保存。 */
|
||||
export async function Download(taskId: number): Promise<Blob> {
|
||||
const response = await requestClient.download<
|
||||
import('axios').AxiosResponse<Blob>
|
||||
>(`/common/downloadCenter/download?taskId=${taskId}`, {
|
||||
timeout: 120 * 1000,
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
const blob = response.data;
|
||||
const contentType = String(
|
||||
response.headers['content-type'] || blob?.type || '',
|
||||
).toLowerCase();
|
||||
if (contentType.includes('json')) {
|
||||
let errorMessage = '下载失败,请稍后重试';
|
||||
try {
|
||||
const payload = JSON.parse(await blob.text());
|
||||
errorMessage = payload?.message || errorMessage;
|
||||
} catch {
|
||||
// Malformed JSON must not be saved as a spreadsheet either.
|
||||
}
|
||||
message.error(errorMessage);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
if (!(blob instanceof Blob) || blob.size === 0) {
|
||||
const errorMessage = '下载文件为空,请稍后重试';
|
||||
message.error(errorMessage);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
/** 删除导出任务 */
|
||||
export function Remove(taskId: number) {
|
||||
return requestClient.post('/common/downloadCenter/remove', { taskId });
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取企业客户财务信息列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tAgentBalance/list', { params });
|
||||
}
|
||||
|
||||
// 获取账户余额概览
|
||||
export function GetAccountBalance(params?: any) {
|
||||
return requestClient.get<any>('common/tAgentBalance/getAccountBalance', { params });
|
||||
}
|
||||
|
||||
// 获取费用总览折线图
|
||||
export function FeeTrend(params: any) {
|
||||
return requestClient.get<any>('common/tAgentBalance/feeTrend', { params });
|
||||
}
|
||||
|
||||
// 获取账户总览折线图
|
||||
export function AccountTrend(params: any) {
|
||||
return requestClient.get<any>('common/tAgentBalance/accountTrend', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除企业客户财务信息
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tAgentBalance/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑企业客户财务信息
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tAgentBalance/edit', { ...params });
|
||||
}
|
||||
|
||||
// 修改企业客户财务信息状态
|
||||
export function Status(params:any) {
|
||||
return requestClient.post<any>('common/tAgentBalance/status', { ...params });
|
||||
}
|
||||
|
||||
// 获取企业客户财务信息指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tAgentBalance/view', { params });
|
||||
}
|
||||
|
||||
// 导出企业客户财务信息
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tAgentBalance/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function AlipayPay(params: any) {
|
||||
return requestClient.post<any>('pay/alipay/pay', params);
|
||||
}
|
||||
|
||||
export function AlipayQuery(params: any) {
|
||||
return requestClient.get<any>('pay/alipay/query', { params });
|
||||
}
|
||||
|
||||
// 转可提现申请
|
||||
export function BalanceTransferApply(params: {
|
||||
amount: number;
|
||||
accountType: number;
|
||||
bankName?: string;
|
||||
bankAccount?: string;
|
||||
accountName?: string;
|
||||
identityCard?: string;
|
||||
remark?: string;
|
||||
}) {
|
||||
return requestClient.post<any>('common/tAgentBalance/balanceTransferApply', params);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取余额明细表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tBalanceDetail/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除余额明细表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tBalanceDetail/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑余额明细表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tBalanceDetail/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取余额明细表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tBalanceDetail/view', { params });
|
||||
}
|
||||
|
||||
// 导出余额明细表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tBalanceDetail/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function Recharge(params:any) {
|
||||
return requestClient.post<any>('common/tBalanceDetail/recharge', { ...params });
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取消费账户月账单表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tConsumeAccountMonthBill/list', { params });
|
||||
}
|
||||
|
||||
// 获取消费账户月账单汇总
|
||||
export function GetConsumptionBillSummary(params:any) {
|
||||
return requestClient.get<any>('common/tConsumeAccountMonthBill/getConsumptionBillSummary', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除消费账户月账单表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tConsumeAccountMonthBill/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑消费账户月账单表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tConsumeAccountMonthBill/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取消费账户月账单表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tConsumeAccountMonthBill/view', { params });
|
||||
}
|
||||
|
||||
// 导出消费账户月账单表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tConsumeAccountMonthBill/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取信用额度明细表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tCreditDetail/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除信用额度明细表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tCreditDetail/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑信用额度明细表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tCreditDetail/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取信用额度明细表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tCreditDetail/view', { params });
|
||||
}
|
||||
|
||||
// 导出信用额度明细表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tCreditDetail/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取分润明细表列表
|
||||
export function List(params: any) {
|
||||
return requestClient.get<any>('common/tFinCommissionDetail/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除分润明细表
|
||||
export function Delete(params: any) {
|
||||
return requestClient.post<any>('common/tFinCommissionDetail/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑分润明细表
|
||||
export function Edit(params: any) {
|
||||
return requestClient.post<any>('common/tFinCommissionDetail/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取分润明细表指定详情
|
||||
export function View(params: any) {
|
||||
return requestClient.get<any>('common/tFinCommissionDetail/view', { params });
|
||||
}
|
||||
|
||||
// 获取分层分润概览
|
||||
export function GetCommissionOverview(params: any) {
|
||||
return requestClient.get<any>(
|
||||
'common/tFinCommissionDetail/getCommissionOverview',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 获取层级汇总表
|
||||
export function GetLevelSummary(params: any) {
|
||||
return requestClient.get<any>(
|
||||
'common/tFinCommissionDetail/getLevelSummary',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 导出分润明细表
|
||||
export function Export(params: any) {
|
||||
return requestClient.post<Blob>(
|
||||
'/common/tFinCommissionDetail/export',
|
||||
{ ...params },
|
||||
{
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取可提现变动明细表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tFinWithdrawableChange/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除可提现变动明细表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tFinWithdrawableChange/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑可提现变动明细表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tFinWithdrawableChange/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取可提现变动明细表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tFinWithdrawableChange/view', { params });
|
||||
}
|
||||
|
||||
// 导出可提现变动明细表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tFinWithdrawableChange/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取财务申请表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tFinanceApply/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除财务申请表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tFinanceApply/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑财务申请表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tFinanceApply/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取财务申请表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tFinanceApply/view', { params });
|
||||
}
|
||||
|
||||
// 导出财务申请表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tFinanceApply/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
// 审核余额转可提现申请
|
||||
export function BalanceTransferAudit(params: {
|
||||
applyNo: string;
|
||||
auditResult: number;
|
||||
auditOpinion?: string;
|
||||
}) {
|
||||
return requestClient.post<any>('common/tAgentBalance/balanceTransferAudit', params);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取财务审核记录表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tFinanceAuditRecord/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除财务审核记录表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tFinanceAuditRecord/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑财务审核记录表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tFinanceAuditRecord/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取财务审核记录表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tFinanceAuditRecord/view', { params });
|
||||
}
|
||||
|
||||
// 导出财务审核记录表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tFinanceAuditRecord/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取消息日志列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tMessageLog/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除消息日志
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tMessageLog/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑消息日志
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tMessageLog/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取消息日志指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tMessageLog/view', { params });
|
||||
}
|
||||
|
||||
// 导出消息日志
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tMessageLog/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
// 未读消息通知(右上角消息提醒)
|
||||
export interface TMessageLogUnreadItem {
|
||||
messageLogId: number;
|
||||
messageType: number;
|
||||
sendUserType: number;
|
||||
messageTitle: string;
|
||||
messageContent: string;
|
||||
messageLink: string;
|
||||
sendTime: string;
|
||||
isRead: number;
|
||||
}
|
||||
|
||||
export interface TMessageLogUnreadResult {
|
||||
items: TMessageLogUnreadItem[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
// 获取当前登录用户未读消息通知(右上角消息提醒)
|
||||
export function UnreadList(params?: { limit?: number }) {
|
||||
return requestClient.get<TMessageLogUnreadResult>('common/tMessageLog/unreadList', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 标记当前登录用户指定消息已读
|
||||
export function Read(params: { messageLogId: number | string }) {
|
||||
return requestClient.post<unknown>('common/tMessageLog/read', { ...params });
|
||||
}
|
||||
|
||||
// 标记当前登录用户全部消息已读
|
||||
export function ReadAll() {
|
||||
return requestClient.post<unknown>('common/tMessageLog/readAll', {});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取通知日志列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tNotifyLog/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除通知日志
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tNotifyLog/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑通知日志
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tNotifyLog/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取通知日志指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tNotifyLog/view', { params });
|
||||
}
|
||||
|
||||
// 导出通知日志
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tNotifyLog/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取盈利账户月账单表列表
|
||||
export function List(params: any) {
|
||||
return requestClient.get<any>('common/tProfitAccountMonthBill/list', { params });
|
||||
}
|
||||
|
||||
// 获取盈利账户月账单汇总
|
||||
export function GetProfitBillSummary(params: any) {
|
||||
return requestClient.get<any>(
|
||||
'common/tProfitAccountMonthBill/getProfitBillSummary',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 获取核心财务指标
|
||||
export function GetCoreFinancialData(params: any) {
|
||||
return requestClient.get<any>(
|
||||
'common/tProfitAccountMonthBill/getCoreFinancialData',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 获取财务趋势
|
||||
export function GetFinancialTrend(params: any) {
|
||||
return requestClient.get<any>(
|
||||
'common/tProfitAccountMonthBill/getFinancialTrend',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 删除/批量删除盈利账户月账单表
|
||||
export function Delete(params: any) {
|
||||
return requestClient.post<any>('common/tProfitAccountMonthBill/delete', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
// 添加/编辑盈利账户月账单表
|
||||
export function Edit(params: any) {
|
||||
return requestClient.post<any>('common/tProfitAccountMonthBill/edit', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
// 获取盈利账户月账单表指定详情
|
||||
export function View(params: any) {
|
||||
return requestClient.get<any>('common/tProfitAccountMonthBill/view', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 导出盈利账户月账单表
|
||||
export function Export(params: any) {
|
||||
return requestClient.post<Blob>(
|
||||
'/common/tProfitAccountMonthBill/export',
|
||||
{ ...params },
|
||||
{
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取工单问题沟通表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('/common/tWoCommunication/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除工单问题沟通表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tWoCommunication/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑工单问题沟通表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tWoCommunication/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取工单问题沟通表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tWoCommunication/view', { params });
|
||||
}
|
||||
|
||||
// 发送工单沟通消息
|
||||
export function Message(params:any) {
|
||||
return requestClient.post<any>('common/tWoCommunication/message', { ...params });
|
||||
}
|
||||
|
||||
// 导出工单问题沟通表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tWoCommunication/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取工单主表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tWoMain/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除工单主表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑工单主表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取工单主表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tWoMain/view', { params });
|
||||
}
|
||||
|
||||
// 工单转单
|
||||
export function Transfer(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/transfer', { ...params });
|
||||
}
|
||||
|
||||
// 工单完成
|
||||
export function Resolve(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/resolve', { ...params });
|
||||
}
|
||||
|
||||
// 工单取消/关闭
|
||||
export function Cancel(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/cancel', { ...params });
|
||||
}
|
||||
|
||||
// 关闭工单
|
||||
export function Close(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/close', { ...params });
|
||||
}
|
||||
|
||||
// 工单评价
|
||||
export function Evaluate(params:any) {
|
||||
return requestClient.post<any>('common/tWoMain/evaluate', { ...params });
|
||||
}
|
||||
|
||||
// 导出工单主表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tWoMain/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取工单记录表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('common/tWoRecord/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除工单记录表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('common/tWoRecord/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑工单记录表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('common/tWoRecord/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取工单记录表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('common/tWoRecord/view', { params });
|
||||
}
|
||||
|
||||
// 导出工单记录表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/common/tWoRecord/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* @description 认证相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import { baseRequestClient, requestClient } from '#/api/request';
|
||||
|
||||
/**
|
||||
* 登录类型
|
||||
* password 密码
|
||||
* sms 短信
|
||||
* social 第三方oauth
|
||||
* email 邮箱
|
||||
* xcx 小程序
|
||||
*/
|
||||
type GrantType = 'email' | 'password' | 'sms' | 'social' | 'xcx';
|
||||
|
||||
export namespace AuthApi {
|
||||
/** 登录接口参数 */
|
||||
export interface LoginParams {
|
||||
password?: string;
|
||||
username?: string;
|
||||
}
|
||||
|
||||
/** 登录接口返回值 */
|
||||
export interface LoginResult {
|
||||
accessToken: string;
|
||||
}
|
||||
/** 注册接口参数 */
|
||||
export interface RegisterParams {
|
||||
tenantId?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
captchaID?: string;
|
||||
captchaValue?: string;
|
||||
}
|
||||
export type RegisterResult = Record<string, never>;
|
||||
|
||||
export interface RefreshTokenResult {
|
||||
data: string;
|
||||
status: number;
|
||||
}
|
||||
|
||||
export interface BaseLoginParams {
|
||||
clientId?: string;
|
||||
grantType: GrantType;
|
||||
tenantId: string;
|
||||
}
|
||||
|
||||
export interface OAuthLoginParams extends BaseLoginParams {
|
||||
socialCode: string;
|
||||
socialState: string;
|
||||
source: string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param companyName 租户/公司名称
|
||||
* @param domain 绑定域名(不带http(s)://) 可选
|
||||
* @param tenantId 租户id
|
||||
*/
|
||||
export interface TenantOption {
|
||||
companyName: string;
|
||||
domain?: string;
|
||||
tenantId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tenantEnabled 是否启用租户
|
||||
* @param voList 租户列表
|
||||
*/
|
||||
export interface TenantResp {
|
||||
tenantEnabled: boolean;
|
||||
voList: TenantOption[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户权限码
|
||||
*/
|
||||
export interface GetAccessCodesResult {
|
||||
data: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
export async function loginApi(data: AuthApi.LoginParams) {
|
||||
return requestClient.post<AuthApi.LoginResult>('/system/auth/login', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送手机验证码登录短信
|
||||
*/
|
||||
export async function sendSmsLoginCodeApi(phone: string) {
|
||||
return requestClient.post('/system/auth/sms-code', { phone });
|
||||
}
|
||||
|
||||
/**
|
||||
* 手机验证码登录
|
||||
*/
|
||||
export async function smsLoginApi(data: { code: string; phone: string }) {
|
||||
return requestClient.post<AuthApi.LoginResult>(
|
||||
'/system/auth/sms-login',
|
||||
data,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 注册register
|
||||
*/
|
||||
|
||||
export async function registerApi(data: AuthApi.RegisterParams) {
|
||||
return requestClient.post<AuthApi.RegisterResult>(
|
||||
'/system/user/register',
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新accessToken
|
||||
*/
|
||||
export async function refreshTokenApi() {
|
||||
return baseRequestClient.post<AuthApi.RefreshTokenResult>(
|
||||
'/system/auth/refresh',
|
||||
undefined,
|
||||
{
|
||||
withCredentials: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
export async function logoutApi() {
|
||||
return requestClient.post('/system/auth/logout', undefined, {
|
||||
withCredentials: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户权限码
|
||||
*/
|
||||
export async function getAccessCodesApi() {
|
||||
return requestClient.get<GetAccessCodesResult>('/system/auth/codes');
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定第三方账号
|
||||
* @param source 绑定的来源
|
||||
* @returns 跳转url
|
||||
*/
|
||||
export function authBinding(source: string, tenantId: string) {
|
||||
return requestClient.get<string>(`/auth/binding/${source}`, {
|
||||
params: {
|
||||
domain: window.location.host,
|
||||
tenantId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消绑定
|
||||
* @param id id
|
||||
*/
|
||||
export function authUnbinding(id: string) {
|
||||
return requestClient.delete<unknown>(`/auth/unlock/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* oauth授权回调
|
||||
* @param data oauth授权
|
||||
* @returns void
|
||||
*/
|
||||
export function authCallback(data: AuthApi.OAuthLoginParams) {
|
||||
return requestClient.post<unknown>('/auth/social/callback', data);
|
||||
}
|
||||
|
||||
// 获取租户列表
|
||||
export function tenantList() {
|
||||
return requestClient.get<TenantResp>('/system/auth/getTenantList');
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @description 验证码相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace CaptchaApi {
|
||||
export interface GetCaptchaResult {
|
||||
captchaID: string;
|
||||
captchaImage: string;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCaptchaApi() {
|
||||
return requestClient.get<CaptchaApi.GetCaptchaResult>('/system/captcha');
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @description 核心模块接口导出
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
export * from './auth';
|
||||
export * from './menu';
|
||||
export * from './user';
|
||||
export * from './captcha';
|
||||
export * from './upload';
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @description 菜单相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import type { RouteRecordStringComponent } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
/**
|
||||
* 获取用户所有菜单
|
||||
*/
|
||||
export async function getAllMenusApi() {
|
||||
return requestClient.get<RouteRecordStringComponent[]>('/system/menu/all');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @description 文件上传相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import type { AxiosRequestConfig } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
/**
|
||||
* Axios上传进度事件
|
||||
*/
|
||||
export type AxiosProgressEvent = AxiosRequestConfig['onUploadProgress'];
|
||||
|
||||
/**
|
||||
* 通过单文件上传接口
|
||||
* @param file 上传的文件
|
||||
* @param onUploadProgress 上传进度事件 非必传
|
||||
* @param isDevice 不知道这是什么,但是不敢动
|
||||
* @param newFileType 新文件类型 1:用户文件 2:用户图片 3:设备文件 4:iot配置图片 5:iot固件文件 6:项目图片 7:项目文件
|
||||
* @param subDirName 文件父目录
|
||||
* @param params 额外上传参数
|
||||
* @returns 上传结果
|
||||
*/
|
||||
export function uploadApi(
|
||||
file: Blob | File,
|
||||
onUploadProgress?: AxiosProgressEvent,
|
||||
isDevice?: boolean | undefined,
|
||||
newFileType?: number,
|
||||
subDirName?: string,
|
||||
params?: Record<string, any>,
|
||||
) {
|
||||
return requestClient.upload(
|
||||
'/common/oss/upload',
|
||||
{
|
||||
...params,
|
||||
file,
|
||||
fileType: 'file',
|
||||
...(isDevice ? { isDevice } : {}),
|
||||
...(newFileType ? { newFileType } : {}),
|
||||
...(subDirName ? { subDirName } : {}),
|
||||
},
|
||||
{ onUploadProgress, timeout: 60_000 },
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 默认上传结果
|
||||
*/
|
||||
export interface UploadResult {
|
||||
url: string;
|
||||
fileName: string;
|
||||
ossId: string;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @description 用户信息相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import type { UserInfo } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export async function getUserInfoApi() {
|
||||
return requestClient.get<UserInfo>('/system/user/info');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取测试分类列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('gen/testCategory/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除测试分类
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('gen/testCategory/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑测试分类
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('gen/testCategory/edit', { ...params });
|
||||
}
|
||||
|
||||
// 修改测试分类状态
|
||||
export function Status(params:any) {
|
||||
return requestClient.post<any>('gen/testCategory/status', { ...params });
|
||||
}
|
||||
|
||||
// 获取测试分类指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('gen/testCategory/view', { params });
|
||||
}
|
||||
|
||||
// 获取测试分类最大排序
|
||||
export function MaxSort(params:any) {
|
||||
return requestClient.get<any>('gen/testCategory/maxSort', { params });
|
||||
}
|
||||
|
||||
// 导出测试分类
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/gen/testCategory/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @description 测试单表相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取测试单表列表
|
||||
export function List(params:any) {
|
||||
return requestClient.get<any>('gen/testDemo/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除测试单表
|
||||
export function Delete(params:any) {
|
||||
return requestClient.post<any>('gen/testDemo/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑测试单表
|
||||
export function Edit(params:any) {
|
||||
return requestClient.post<any>('gen/testDemo/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取测试单表指定详情
|
||||
export function View(params:any) {
|
||||
return requestClient.get<any>('gen/testDemo/view', { params });
|
||||
}
|
||||
|
||||
// 导出测试单表
|
||||
export function Export(params:any) {
|
||||
return requestClient.post<Blob>('/gen/testDemo/export', { ...params } , {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* @description 代码生成器表格相关接口
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
import type { DictOption } from '#/store/dict';
|
||||
|
||||
export interface SysGenTableListReq {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
genType: number;
|
||||
varName: string;
|
||||
status: string;
|
||||
}
|
||||
export interface SysGenTableListModel {
|
||||
tableId: number; // 生成ID
|
||||
genType: number; // 生成类型
|
||||
genTemplate: number; // 生成模板
|
||||
varName: string; // 实体命名
|
||||
options: string; // 配置选项
|
||||
dbName: string; // 数据库名称
|
||||
tableName: string; // 主表名称
|
||||
tableComment: string; // 主表注释
|
||||
daoName: string; // 主表dao模型
|
||||
masterColumns: string; // 主表字段
|
||||
addonName: string; // 插件名称
|
||||
status: string; // 生成状态(0成功
|
||||
createdDept: number; // 创建组织
|
||||
createdBy: number; // 创建者
|
||||
createdAt: string; // 创建时间
|
||||
}
|
||||
export interface SysGenTableListRes {
|
||||
items: SysGenTableListModel[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
export async function getSysGenTableListApi(params: SysGenTableListReq) {
|
||||
return requestClient.get<SysGenTableListRes>('/genCodes/genTable/list', { params });
|
||||
}
|
||||
|
||||
|
||||
export interface SysGenTableAddReq {
|
||||
genType: number;
|
||||
genTemplate: number;
|
||||
varName: string;
|
||||
options: string;
|
||||
dbName: string;
|
||||
tableName: string;
|
||||
tableComment: string;
|
||||
daoName: string;
|
||||
masterColumns: string;
|
||||
addonName: string;
|
||||
}
|
||||
export interface SysGenTableAddRes {
|
||||
tableId: number;
|
||||
}
|
||||
export interface SysGenTableEditReq {
|
||||
tableId: number;
|
||||
genType?: number;
|
||||
genTemplate?: number;
|
||||
varName?: string;
|
||||
options?: any;
|
||||
dbName?: string;
|
||||
tableName?: string;
|
||||
tableComment?: string;
|
||||
daoName?: string;
|
||||
masterColumns?: any;
|
||||
addonName?: string;
|
||||
}
|
||||
|
||||
export interface SysGenTableEditRes {
|
||||
tableId: number;
|
||||
}
|
||||
|
||||
export interface SysGenTableDeleteReq {
|
||||
tableIds: number[];
|
||||
}
|
||||
export interface SysGenTableDeleteRes {
|
||||
tableIds: number[];
|
||||
}
|
||||
export interface SysGenTableJoinModel {
|
||||
uuid: string;
|
||||
dbName: string;
|
||||
masterTableName: string;
|
||||
linkTable: string;
|
||||
alias: string;
|
||||
linkMode: number;
|
||||
field: string;
|
||||
masterField: string;
|
||||
daoName: string;
|
||||
columns: GenCodesColumn[];
|
||||
}
|
||||
|
||||
export interface SysGenTableTreeModel {
|
||||
titleColumn: string;
|
||||
styleType: number;
|
||||
}
|
||||
export interface SysGenTableMenuModel {
|
||||
icon: string;
|
||||
pid: number;
|
||||
sort: number;
|
||||
}
|
||||
export interface SysGenTableFuncDictModel {
|
||||
valueColumn: string|null ;
|
||||
labelColumn: string|null;
|
||||
}
|
||||
export interface SysGenTablePresetStepModel {
|
||||
formGridCols: number;
|
||||
}
|
||||
export interface SysGenTableOptionsModel {
|
||||
headOps?: string[];
|
||||
columnOps?: string[];
|
||||
autoOps?: string[];
|
||||
join?:any[];
|
||||
menu?:SysGenTableMenuModel;
|
||||
funcDict?: SysGenTableFuncDictModel;
|
||||
presetStep?:SysGenTablePresetStepModel;
|
||||
tree?:SysGenTableTreeModel;
|
||||
}
|
||||
|
||||
export interface SysGenTableViewReq {
|
||||
tableId: number;
|
||||
}
|
||||
|
||||
|
||||
export interface SysGenTableViewRes {
|
||||
tableId: number;
|
||||
genType: number;
|
||||
genTemplate: number;
|
||||
varName: string;
|
||||
options: SysGenTableOptionsModel|string;
|
||||
dbName: string;
|
||||
tableName: string;
|
||||
tableComment: string;
|
||||
daoName: string;
|
||||
masterColumns: GenCodesColumn[]|string;
|
||||
addonName: string;
|
||||
status: string;
|
||||
createdDept: number;
|
||||
createdBy: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export async function addSysGenTableApi(params: SysGenTableAddReq | {
|
||||
[x: string]: any;
|
||||
}) {
|
||||
return requestClient.post<SysGenTableAddRes>('/genCodes/genTable/add', { ...params });
|
||||
}
|
||||
|
||||
|
||||
export async function deleteSysGenTableApi(params: SysGenTableDeleteReq) {
|
||||
return requestClient.post<SysGenTableDeleteRes>('/genCodes/genTable/delete', { ...params });
|
||||
}
|
||||
|
||||
export async function editSysGenTableApi(params: SysGenTableEditReq) {
|
||||
return requestClient.post<SysGenTableEditRes>('/genCodes/genTable/edit', { ...params });
|
||||
}
|
||||
|
||||
export async function getSysGenTableViewApi(params: SysGenTableViewReq) {
|
||||
return requestClient.get<SysGenTableViewRes>('/genCodes/genTable/view', { params });
|
||||
}
|
||||
|
||||
|
||||
export interface SelectItemModel {
|
||||
value: string|number;
|
||||
label: string;
|
||||
name: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export interface SelectGenTypeModel extends SelectItemModel,DictOption {
|
||||
templates: SelectGenTemplateModel[];
|
||||
}
|
||||
|
||||
export interface SelectGenTemplateModel extends SelectItemModel {
|
||||
isAddon: boolean;
|
||||
}
|
||||
|
||||
export interface GenCodesSelect {
|
||||
genType: SelectGenTypeModel[];
|
||||
db: SelectItemModel[];
|
||||
status: SelectItemModel[];
|
||||
linkMode: SelectItemModel[];
|
||||
buildMethod: SelectItemModel[];
|
||||
formMode: SelectItemModel[];
|
||||
formRole: SelectItemModel[];
|
||||
whereMode: SelectItemModel[];
|
||||
addons: SelectItemModel[];
|
||||
tableAlign: SelectItemModel[];
|
||||
treeStyleType: SelectItemModel[];
|
||||
dictMode: SelectItemModel[];
|
||||
}
|
||||
|
||||
|
||||
export interface GenCodesSelectsReq {
|
||||
}
|
||||
|
||||
export interface GenCodesSelectsRes extends GenCodesSelect {
|
||||
|
||||
}
|
||||
|
||||
export async function getGenCodesSelectsApi(params: GenCodesSelectsReq) {
|
||||
return requestClient.get<GenCodesSelectsRes>('/genCodes/genTable/selects', { params });
|
||||
}
|
||||
|
||||
export interface DbTableSelectModel {
|
||||
value: string;
|
||||
label: string;
|
||||
name: string;
|
||||
daoName: string;
|
||||
defVarName: string;
|
||||
defAlias: string;
|
||||
defTableComment: string;
|
||||
}
|
||||
export interface GenCodesTableSelectReq {
|
||||
dbGroup: string;
|
||||
}
|
||||
|
||||
export interface GenCodesTableSelectRes {
|
||||
items: DbTableSelectModel[];
|
||||
}
|
||||
|
||||
export async function getGenCodesTableSelectApi(params: GenCodesTableSelectReq) {
|
||||
return requestClient.get<GenCodesTableSelectRes>('/genCodes/genTable/tableSelect', { params });
|
||||
}
|
||||
|
||||
export interface DbColumnSelectModel {
|
||||
value: string;
|
||||
label: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GenCodesColumnSelectReq {
|
||||
dbGroup: string;
|
||||
tableName: string;
|
||||
}
|
||||
export interface GenCodesColumnSelectRes {
|
||||
items: DbColumnSelectModel[];
|
||||
}
|
||||
|
||||
export async function getGenCodesColumnSelectApi(params: GenCodesColumnSelectReq) {
|
||||
return requestClient.get<GenCodesColumnSelectRes>('/genCodes/genTable/columnSelect', { params });
|
||||
}
|
||||
|
||||
export interface GenCodesColumn {
|
||||
id: number;
|
||||
name: string;
|
||||
dc: string;
|
||||
dataType: string;
|
||||
sqlType: string;
|
||||
length: number;
|
||||
isAllowNull: boolean;
|
||||
defaultValue: any;
|
||||
index: string;
|
||||
extra: string;
|
||||
goName: string;
|
||||
goType: string;
|
||||
tsName: string;
|
||||
tsType: string;
|
||||
isList: boolean;
|
||||
isExport: boolean;
|
||||
isSort: boolean;
|
||||
isQuery: boolean;
|
||||
queryWhere: string;
|
||||
isEdit: boolean;
|
||||
required: boolean;
|
||||
unique: boolean;
|
||||
formMode: string;
|
||||
formRole: string;
|
||||
formGridSpan: number;
|
||||
dictType: number;
|
||||
align: string;
|
||||
width: number;
|
||||
}
|
||||
export interface GenCodesColumnListModel extends GenCodesColumn {
|
||||
|
||||
}
|
||||
|
||||
export interface GenCodesColumnListParam {
|
||||
dbGroup: string;
|
||||
tableName: string;
|
||||
isLink: number;
|
||||
alias: string;
|
||||
}
|
||||
export interface GenCodesColumnListRes {
|
||||
items: GenCodesColumnListModel[];
|
||||
}
|
||||
|
||||
export async function getGenCodesColumnListApi(params: GenCodesColumnListParam) {
|
||||
return requestClient.get<GenCodesColumnListRes>('/genCodes/genTable/columnList', { params });
|
||||
}
|
||||
|
||||
export interface GenCodesPreviewReq extends SysGenTableListModel {
|
||||
|
||||
}
|
||||
export interface GenFile {
|
||||
content: string;
|
||||
path: string;
|
||||
meth: number;
|
||||
required: boolean;
|
||||
}
|
||||
export interface GenCodesPreviewRes {
|
||||
views: Record<string, GenFile>;
|
||||
config?: any;
|
||||
}
|
||||
|
||||
export async function postGenCodesPreviewApi(params: GenCodesPreviewReq) {
|
||||
return requestClient.post<GenCodesPreviewRes>('/genCodes/genTable/preview', { ...params });
|
||||
}
|
||||
|
||||
export interface GenCodesBuildReq extends GenCodesPreviewReq {
|
||||
|
||||
}
|
||||
export interface GenCodesBuildRes {
|
||||
|
||||
}
|
||||
|
||||
export async function postGenCodesBuildApi(params: GenCodesBuildReq) {
|
||||
return requestClient.post<GenCodesBuildRes>('/genCodes/genTable/build', { ...params });
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @description API接口统一导出
|
||||
* @Link https://github.com/xiujiecn/xiu-admin
|
||||
* @Copyright Copyright (c) 2025 LiXiujie
|
||||
* @Author Lxj <xxx@example.com>
|
||||
* @License https://github.com/xiujiecn/xiu-admin/blob/master/LICENSE
|
||||
* @date 2024-03-21
|
||||
*/
|
||||
|
||||
export * from './core';
|
||||
export * from './system';
|
||||
@@ -0,0 +1,47 @@
|
||||
import type {
|
||||
TApiDeleteParam,
|
||||
TApiEditParam,
|
||||
TApiExportParam,
|
||||
TApiListParam,
|
||||
TApiListRes,
|
||||
TApiViewParam,
|
||||
TApiViewRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取API集成列表
|
||||
export function List(params: TApiListParam) {
|
||||
return requestClient.get<TApiListRes>('agent/tApi/list', { params });
|
||||
}
|
||||
|
||||
// 删除/批量删除API集成
|
||||
export function Delete(params: TApiDeleteParam) {
|
||||
return requestClient.post('agent/tApi/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑API集成
|
||||
export function Edit(params: TApiEditParam) {
|
||||
return requestClient.post('agent/tApi/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取API集成指定详情
|
||||
export function View(params: TApiViewParam) {
|
||||
return requestClient.get<TApiViewRes>('agent/tApi/view', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 导出API集成
|
||||
export function Export(params: TApiExportParam) {
|
||||
return requestClient.post<Blob>(
|
||||
'/agent/tApi/export',
|
||||
{ ...params },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
},
|
||||
responseType: 'blob',
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import type { GlobalListRes } from '#/types/global';
|
||||
import type { MemberSumma } from '#/utils';
|
||||
|
||||
/** API集成列表项 */
|
||||
export interface TApiModel {
|
||||
/** ID */
|
||||
id: number;
|
||||
/** APPKey */
|
||||
appKey: string;
|
||||
/** APPSecret */
|
||||
appSecret: string;
|
||||
/** API分组 */
|
||||
groupId: number;
|
||||
/** 限流周期(秒,0:不限流) */
|
||||
rateLimitPeriod: number;
|
||||
/** 限流次数 */
|
||||
rateLimitCount: number;
|
||||
/** 所属机构 */
|
||||
deptId: number;
|
||||
/** 客户编号 */
|
||||
deptKey: string;
|
||||
/** 客户名称 */
|
||||
deptName: string;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/** 获取API集成列表 请求参数 */
|
||||
export interface TApiListParam {
|
||||
/** 页码 */
|
||||
page?: number;
|
||||
/** 每页大小 */
|
||||
pageSize?: number;
|
||||
/** 关键字 */
|
||||
keyword?: string;
|
||||
/** ID */
|
||||
id?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string[];
|
||||
}
|
||||
|
||||
/** 获取API集成列表 响应 */
|
||||
export type TApiListRes = GlobalListRes<TApiModel>;
|
||||
|
||||
/** 导出API集成列表 请求参数 */
|
||||
export type TApiExportParam = TApiListParam;
|
||||
|
||||
/** 修改/新增API集成 请求参数 */
|
||||
export interface TApiEditParam {
|
||||
/** ID */
|
||||
id?: number;
|
||||
/** APPKey */
|
||||
appKey?: string;
|
||||
/** APPSecret */
|
||||
appSecret?: string;
|
||||
/** API分组 */
|
||||
groupId?: number;
|
||||
/** 限流周期(秒,0:不限流) */
|
||||
rateLimitPeriod?: number;
|
||||
/** 限流次数 */
|
||||
rateLimitCount?: number;
|
||||
/** 所属机构 */
|
||||
deptId?: number;
|
||||
/** 租户ID */
|
||||
tenantId?: string;
|
||||
/** 创建部门 */
|
||||
createdDept?: number;
|
||||
/** 创建者 */
|
||||
createdBy?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
/** 更新者 */
|
||||
updatedBy?: number;
|
||||
/** 更新时间 */
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
/** 获取API集成指定信息 请求参数 */
|
||||
export interface TApiViewParam {
|
||||
/** APPKey */
|
||||
appKey: string;
|
||||
}
|
||||
|
||||
/** 获取API集成指定信息 响应 */
|
||||
export type TApiViewRes = TApiModel;
|
||||
|
||||
/** 删除API集成 请求参数 */
|
||||
export interface TApiDeleteParam {
|
||||
/** 主键ID */
|
||||
id: number | number[];
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import type {
|
||||
TSimChannelTemplateDeleteParam,
|
||||
TSimChannelTemplateEditParam,
|
||||
TSimChannelTemplateExportParam,
|
||||
TSimChannelTemplateListParam,
|
||||
TSimChannelTemplateListRes,
|
||||
TSimChannelTemplateViewParam,
|
||||
TSimChannelTemplateViewRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取通道模板列表
|
||||
export function List(params: TSimChannelTemplateListParam) {
|
||||
return requestClient.get<TSimChannelTemplateListRes>(
|
||||
'iot/tSimChannelTemplate/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
// 删除/批量删除通道模板
|
||||
export function Delete(params: TSimChannelTemplateDeleteParam) {
|
||||
return requestClient.post('iot/tSimChannelTemplate/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑通道模板
|
||||
export function Edit(params: TSimChannelTemplateEditParam) {
|
||||
return requestClient.post('iot/tSimChannelTemplate/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取通道模板指定详情
|
||||
export function View(params: TSimChannelTemplateViewParam) {
|
||||
return requestClient.get<TSimChannelTemplateViewRes>(
|
||||
'iot/tSimChannelTemplate/view',
|
||||
{
|
||||
params,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 导出通道模板
|
||||
export function Export(params: TSimChannelTemplateExportParam) {
|
||||
return requestClient.post<Blob>(
|
||||
'/iot/tSimChannelTemplate/export',
|
||||
{ ...params },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
},
|
||||
responseType: 'blob',
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import type { GlobalListRes } from '#/types/global';
|
||||
import type { MemberSumma } from '#/utils';
|
||||
|
||||
/** 通道模板列表项 */
|
||||
export interface TSimChannelTemplateModel {
|
||||
/** ID */
|
||||
id: number;
|
||||
/** 模板标识 */
|
||||
tempKey: string;
|
||||
/** 模板名称 */
|
||||
tempName: string;
|
||||
/** 模板模型 */
|
||||
tempModel: string;
|
||||
/** 模板配置 */
|
||||
tempConfig: string;
|
||||
/** 模板状态(0未启用,1启用) */
|
||||
tempStatus: number;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/** 获取通道模板指定信息响应项 */
|
||||
export interface TSimChannelTemplateViewModel {
|
||||
/** ID */
|
||||
id: number;
|
||||
/** 模板标识 */
|
||||
tempKey: string;
|
||||
/** 模板名称 */
|
||||
tempName: string;
|
||||
/** 模板模型 */
|
||||
tempModel: string;
|
||||
/** 模板配置 */
|
||||
tempConfig: string;
|
||||
/** 模板状态(0未启用,1启用) */
|
||||
tempStatus: number;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
}
|
||||
|
||||
/** 获取通道模板列表 请求参数 */
|
||||
export interface TSimChannelTemplateListParam {
|
||||
/** 页码 */
|
||||
page?: number;
|
||||
/** 每页大小 */
|
||||
pageSize?: number;
|
||||
/** 关键字 */
|
||||
keyword?: string;
|
||||
/** ID */
|
||||
id?: number;
|
||||
/** 模板标识 */
|
||||
tempKey?: string;
|
||||
/** 模板名称 */
|
||||
tempName?: string;
|
||||
/** 模板模型 */
|
||||
tempModel?: string;
|
||||
/** 模板状态(0未启用,1启用) */
|
||||
tempStatus?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string[];
|
||||
}
|
||||
|
||||
/** 获取通道模板列表 响应 */
|
||||
export type TSimChannelTemplateListRes = GlobalListRes<TSimChannelTemplateModel>;
|
||||
|
||||
/** 导出通道模板列表 请求参数 */
|
||||
export type TSimChannelTemplateExportParam = TSimChannelTemplateListParam;
|
||||
|
||||
/** 修改/新增通道模板 请求参数 */
|
||||
export interface TSimChannelTemplateEditParam {
|
||||
/** ID */
|
||||
id?: number;
|
||||
/** 模板标识 */
|
||||
tempKey?: string;
|
||||
/** 模板名称 */
|
||||
tempName?: string;
|
||||
/** 模板模型 */
|
||||
tempModel?: string;
|
||||
/** 模板配置 */
|
||||
tempConfig?: string;
|
||||
/** 模板状态(0未启用,1启用) */
|
||||
tempStatus?: number;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 租户ID */
|
||||
tenantId?: string;
|
||||
/** 创建部门 */
|
||||
createdDept?: number;
|
||||
/** 创建者 */
|
||||
createdBy?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
/** 更新者 */
|
||||
updatedBy?: number;
|
||||
/** 更新时间 */
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
/** 获取通道模板指定信息 请求参数 */
|
||||
export interface TSimChannelTemplateViewParam {
|
||||
/** ID */
|
||||
id: number;
|
||||
}
|
||||
|
||||
/** 获取通道模板指定信息 响应 */
|
||||
export type TSimChannelTemplateViewRes = TSimChannelTemplateViewModel;
|
||||
|
||||
/** 删除通道模板 请求参数 */
|
||||
export interface TSimChannelTemplateDeleteParam {
|
||||
/** 主键ID */
|
||||
id: number | number[];
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import type {
|
||||
TSimChannelsDeleteParam,
|
||||
TSimChannelsEditParam,
|
||||
TSimChannelsExportParam,
|
||||
TSimChannelsListParam,
|
||||
TSimChannelsListRes,
|
||||
TSimChannelsTestParam,
|
||||
TSimChannelsTestRes,
|
||||
TSimChannelsViewParam,
|
||||
TSimChannelsViewRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取通道管理列表
|
||||
export function List(params: TSimChannelsListParam) {
|
||||
return requestClient.get<TSimChannelsListRes>('iot/tSimChannels/list', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除/批量删除通道管理
|
||||
export function Delete(params: TSimChannelsDeleteParam) {
|
||||
return requestClient.post('iot/tSimChannels/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑通道管理
|
||||
export function Edit(params: TSimChannelsEditParam) {
|
||||
return requestClient.post('iot/tSimChannels/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取通道管理指定详情
|
||||
export function View(params: TSimChannelsViewParam) {
|
||||
return requestClient.get<TSimChannelsViewRes>('iot/tSimChannels/view', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 导出通道管理
|
||||
export function Export(params: TSimChannelsExportParam) {
|
||||
return requestClient.post<Blob>(
|
||||
'/iot/tSimChannels/export',
|
||||
{ ...params },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
},
|
||||
responseType: 'blob',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function Test(params: TSimChannelsTestParam) {
|
||||
return requestClient.post<TSimChannelsTestRes>('iot/tSimChannels/test', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 刷新通道卡数量统计 */
|
||||
export function RefreshCardCount() {
|
||||
return requestClient.post('iot/tSimChannels/refresh-card-count');
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
import type { GlobalListRes } from '#/types/global';
|
||||
import type { MemberSumma } from '#/utils';
|
||||
|
||||
/** 通道管理列表项 */
|
||||
export interface TSimChannelsModel {
|
||||
/** 库存卡数量 */
|
||||
stockCardCount: number;
|
||||
/** 卡信息数量 */
|
||||
cardInfoCount: number;
|
||||
/** 销户卡数量 */
|
||||
cancellationCardCount: number;
|
||||
/** ID */
|
||||
id: number;
|
||||
/** 运营商:1移动,2联通,3电信 */
|
||||
operator: number;
|
||||
/** 模板标识 */
|
||||
tempKey: string;
|
||||
/** 是否允许同步:0否 1是 */
|
||||
syncEnabled: number;
|
||||
/** 模板名称 */
|
||||
tempName: string;
|
||||
/** 模板模型,用于识别共享 Token 能力 */
|
||||
tempModel?: string;
|
||||
/** 通道编号 */
|
||||
chanKey: string;
|
||||
/** 通道名称 */
|
||||
chanName: string;
|
||||
/** 通道配置 */
|
||||
chanConfig: string;
|
||||
/** 通道状态(0未启用,1启用) */
|
||||
chanStatus: number;
|
||||
/** 是否开放共享Token(0否,1是) */
|
||||
shareEnabled: number;
|
||||
/** 是否正常(0是,1否) */
|
||||
isNormal: null | number;
|
||||
/** 对接信息 */
|
||||
dockingStatus: null | number;
|
||||
/** 通道别名 */
|
||||
chanAlias: string;
|
||||
/** 通道行政区域代码(省市) */
|
||||
regionCode: string;
|
||||
/** 应用标识 */
|
||||
appKey: string;
|
||||
/** 应用密钥 */
|
||||
appSecret: string;
|
||||
/** 接口调用凭证 */
|
||||
accessToken: string;
|
||||
/** 凭证申请时间 */
|
||||
accessTokenCreated: string;
|
||||
/** 凭证过期时间 */
|
||||
accessTokenExpire: string;
|
||||
/** 刷新凭证 */
|
||||
refreshToken: string;
|
||||
/** 刷新凭证申请时间 */
|
||||
refreshTokenCreated: string;
|
||||
/** 刷新凭证过期时间 */
|
||||
refreshTokenExpire: string;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 登录账号 */
|
||||
loginUser: string;
|
||||
/** 登录密码 */
|
||||
loginPassword: string;
|
||||
/** 登录地址 */
|
||||
loginUrl: string;
|
||||
/** 登录状态(0未启用,1启用) */
|
||||
loginState: number;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/** 获取通道管理指定信息响应项 */
|
||||
export interface TSimChannelsViewModel {
|
||||
/** ID */
|
||||
id: number;
|
||||
/** 运营商:1移动,2联通,3电信 */
|
||||
operator: number;
|
||||
/** 模板标识 */
|
||||
tempKey: string;
|
||||
/** 是否允许同步:0否 1是 */
|
||||
syncEnabled: number;
|
||||
/** 模板模型,用于识别共享 Token 能力 */
|
||||
tempModel?: string;
|
||||
/** 通道编号 */
|
||||
chanKey: string;
|
||||
/** 通道名称 */
|
||||
chanName: string;
|
||||
/** 通道配置 */
|
||||
chanConfig: string;
|
||||
/** 通道状态(0启用,1停用) */
|
||||
chanStatus: number;
|
||||
/** 是否开放共享Token(0否,1是) */
|
||||
shareEnabled: number;
|
||||
/** 是否正常(0是,1否) */
|
||||
isNormal: null | number;
|
||||
/** 对接信息 */
|
||||
dockingStatus: null | number;
|
||||
/** 通道别名 */
|
||||
chanAlias: string;
|
||||
/** 通道行政区域代码(省市) */
|
||||
regionCode: string;
|
||||
/** 应用标识 */
|
||||
appKey: string;
|
||||
/** 应用密钥 */
|
||||
appSecret: string;
|
||||
/** 接口调用凭证 */
|
||||
accessToken: string;
|
||||
/** 凭证申请时间 */
|
||||
accessTokenCreated: string;
|
||||
/** 凭证过期时间 */
|
||||
accessTokenExpire: string;
|
||||
/** 刷新凭证 */
|
||||
refreshToken: string;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 登录账号 */
|
||||
loginUser: string;
|
||||
/** 登录密码 */
|
||||
loginPassword: string;
|
||||
/** 登录地址 */
|
||||
loginUrl: string;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
/** 模板名称 */
|
||||
tempName: string;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
}
|
||||
|
||||
/** 获取通道管理列表 请求参数 */
|
||||
export interface TSimChannelsListParam {
|
||||
/** 页码 */
|
||||
page?: number;
|
||||
/** 每页大小 */
|
||||
pageSize?: number;
|
||||
/** 关键字 */
|
||||
keyword?: string;
|
||||
/** ID */
|
||||
id?: number;
|
||||
/** 运营商:1移动,2联通,3电信 */
|
||||
operator?: number;
|
||||
/** 模板标识 */
|
||||
tempKey?: string;
|
||||
/** 通道编号 */
|
||||
chanKey?: string;
|
||||
/** 通道名称 */
|
||||
chanName?: string;
|
||||
/** 通道别名 */
|
||||
chanAlias?: string;
|
||||
/** 通道状态(0未启用,1启用) */
|
||||
chanStatus?: number;
|
||||
shareEnabled?: number;
|
||||
isNormal?: number | null;
|
||||
dockingStatus?: number | null;
|
||||
syncEnabled?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string[];
|
||||
}
|
||||
|
||||
/** 获取通道管理列表 响应 */
|
||||
export type TSimChannelsListRes = GlobalListRes<TSimChannelsModel>;
|
||||
|
||||
/** 导出通道管理列表 请求参数 */
|
||||
export type TSimChannelsExportParam = TSimChannelsListParam;
|
||||
|
||||
/** 修改/新增通道管理 请求参数 */
|
||||
export interface TSimChannelsEditParam {
|
||||
/** ID */
|
||||
id?: number;
|
||||
/** 运营商:1移动,2联通,3电信 */
|
||||
operator?: number;
|
||||
/** 模板标识 */
|
||||
tempKey?: string;
|
||||
/** 通道编号 */
|
||||
chanKey?: string;
|
||||
/** 通道名称 */
|
||||
chanName?: string;
|
||||
/** 通道配置 */
|
||||
chanConfig?: string;
|
||||
/** 通道状态(0未启用,1启用) */
|
||||
chanStatus?: number;
|
||||
/** 是否开放共享Token(0否,1是) */
|
||||
shareEnabled?: number;
|
||||
/** 是否正常(0是,1否) */
|
||||
isNormal?: null | number;
|
||||
/** 对接信息 */
|
||||
dockingStatus?: null | number;
|
||||
/** 通道别名 */
|
||||
chanAlias?: string;
|
||||
/** 通道行政区域代码(省市) */
|
||||
regionCode?: string;
|
||||
/** 应用标识 */
|
||||
appKey?: string;
|
||||
/** 应用密钥 */
|
||||
appSecret?: string;
|
||||
/** 接口调用凭证 */
|
||||
accessToken?: string;
|
||||
/** 凭证申请时间 */
|
||||
accessTokenCreated?: string;
|
||||
/** 凭证过期时间 */
|
||||
accessTokenExpire?: string;
|
||||
/** 刷新凭证 */
|
||||
refreshToken?: string;
|
||||
/** 刷新凭证申请时间 */
|
||||
refreshTokenCreated?: string;
|
||||
/** 刷新凭证过期时间 */
|
||||
refreshTokenExpire?: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 登录账号 */
|
||||
loginUser?: string;
|
||||
/** 登录密码 */
|
||||
loginPassword?: string;
|
||||
/** 登录地址 */
|
||||
loginUrl?: string;
|
||||
/** 登录状态(0未启用,1启用) */
|
||||
loginState?: number;
|
||||
/** 租户ID */
|
||||
tenantId?: string;
|
||||
/** 创建部门 */
|
||||
createdDept?: number;
|
||||
/** 创建者 */
|
||||
createdBy?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
/** 更新者 */
|
||||
updatedBy?: number;
|
||||
/** 更新时间 */
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
/** 获取通道管理指定信息 请求参数 */
|
||||
export interface TSimChannelsViewParam {
|
||||
/** ID */
|
||||
id: number;
|
||||
}
|
||||
|
||||
/** 获取通道管理指定信息 响应 */
|
||||
export type TSimChannelsViewRes = TSimChannelsViewModel;
|
||||
|
||||
/** 删除通道管理 请求参数 */
|
||||
export interface TSimChannelsDeleteParam {
|
||||
/** 主键ID */
|
||||
id: number | number[];
|
||||
}
|
||||
|
||||
/** 通道测试请求参数 */
|
||||
export interface TSimChannelsTestParam {
|
||||
channelId: number;
|
||||
inputMode: 'complete' | 'direct_single' | 'single';
|
||||
cardValueType?: 'iccid' | 'imsi' | 'msisdn';
|
||||
cardValue?: string;
|
||||
iccid?: string;
|
||||
imsi?: string;
|
||||
msisdn?: string;
|
||||
/** 未传时执行全部查询项 */
|
||||
items?: string[];
|
||||
}
|
||||
|
||||
export type TSimChannelsTestItemStatus = 'failed' | 'success' | 'timeout';
|
||||
|
||||
/** 单项测试结果 */
|
||||
export interface TSimChannelsTestItem {
|
||||
key: string;
|
||||
name: string;
|
||||
status: TSimChannelsTestItemStatus;
|
||||
durationMs: number;
|
||||
errorCode?: number;
|
||||
message?: string;
|
||||
data?: unknown;
|
||||
/** 完整通道测试响应 JSON,归属当前单项展示 */
|
||||
responseJson?: string;
|
||||
}
|
||||
|
||||
/** 通道测试响应 */
|
||||
export interface TSimChannelsTestRes {
|
||||
items: TSimChannelsTestItem[];
|
||||
/** Unmodified response body from the channel gateway test endpoint. */
|
||||
gatewayResponseRaw?: string;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import type {
|
||||
TSimCardAllocateBatchSubmitParam,
|
||||
TSimCardAllocateBatchSubmitRes,
|
||||
TSimCardAllocateExcelSubmitParam,
|
||||
TSimCardAllocateInputPrepareParam,
|
||||
TSimCardAllocatePrepareRes,
|
||||
TSimCardAllocateTarget,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardAllocate/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ListTargets(keyword = '') {
|
||||
return requestClient.get<{ items: TSimCardAllocateTarget[] }>(
|
||||
'/iot/tSimCardAllocate/targets',
|
||||
{ params: { keyword } },
|
||||
);
|
||||
}
|
||||
|
||||
export function InputPrepare(params: TSimCardAllocateInputPrepareParam) {
|
||||
return requestClient.post<TSimCardAllocatePrepareRes>(
|
||||
'/iot/tSimCardAllocate/input/prepare',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
export function ExcelSubmit(params: TSimCardAllocateExcelSubmitParam) {
|
||||
const data: Record<string, any> & { file: File } = {
|
||||
file: params.file,
|
||||
remark: params.remark ?? '',
|
||||
};
|
||||
if (params.targetDeptId) {
|
||||
data.targetDeptId = String(params.targetDeptId);
|
||||
}
|
||||
return requestClient.upload<TSimCardAllocatePrepareRes>(
|
||||
'/iot/tSimCardAllocate/excel/submit',
|
||||
data,
|
||||
{ timeout: 10 * 60_000 },
|
||||
);
|
||||
}
|
||||
|
||||
export function BatchSubmit(params: TSimCardAllocateBatchSubmitParam) {
|
||||
return requestClient.post<TSimCardAllocateBatchSubmitRes>(
|
||||
'/iot/tSimCardAllocate/batch/submit',
|
||||
params,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
export interface TSimCardAllocateTarget {
|
||||
deptId: number;
|
||||
parentId: number;
|
||||
deptKey?: string;
|
||||
deptName: string;
|
||||
deptCategory?: string;
|
||||
}
|
||||
|
||||
export interface TSimCardAllocateInputPrepareParam {
|
||||
input: string;
|
||||
targetDeptId: number;
|
||||
}
|
||||
|
||||
export interface TSimCardAllocateExcelSubmitParam {
|
||||
file: File;
|
||||
targetDeptId?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface TSimCardAllocateBatchSubmitParam {
|
||||
batchNo: string;
|
||||
targetDeptId?: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
export interface TSimCardAllocateBatchDetail {
|
||||
rowNo: number;
|
||||
itemId: string;
|
||||
targetDeptId?: number;
|
||||
targetDeptKey?: string;
|
||||
targetDeptName?: string;
|
||||
status: string;
|
||||
errorReason?: string;
|
||||
}
|
||||
|
||||
export interface TSimCardAllocatePrepareRes {
|
||||
batchNo: string;
|
||||
batchType: number;
|
||||
batchAsyncStatus?: number;
|
||||
target?: TSimCardAllocateTarget;
|
||||
totalCount: number;
|
||||
validCount: number;
|
||||
failCount: number;
|
||||
failReason?: string;
|
||||
status: string;
|
||||
details: TSimCardAllocateBatchDetail[];
|
||||
}
|
||||
|
||||
export type TSimCardAllocateBatchSubmitRes = TSimCardAllocatePrepareRes;
|
||||
@@ -0,0 +1,94 @@
|
||||
import type {
|
||||
TSimAddPackageBatchConfirmParam,
|
||||
TSimAddPackageBatchConfirmRes,
|
||||
TSimAddPackageOptionsRes,
|
||||
TSimAddPackagePrepareResult,
|
||||
TSimBindPackageAddPackageExcelSubmitParam,
|
||||
TSimBindPackageAddPackageInputPrepareParam,
|
||||
TSimBindPackageAddPackageInputPrepareRes,
|
||||
TSimBindPackageAddPackageInputSubmitParam,
|
||||
TSimBindPackageAddPackageSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取卡绑定套餐列表
|
||||
export function List(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardBindPkg/list', { params });
|
||||
}
|
||||
|
||||
// 获取卡套餐详情
|
||||
export function GetPkgInfo(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardBindPkg/getPkgInfo', { params });
|
||||
}
|
||||
|
||||
// 获取变更套餐
|
||||
export function GetChangePkg(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardBindPkg/getChangePkg', { params });
|
||||
}
|
||||
|
||||
export function DownloadAddPackageTemplate() {
|
||||
return requestClient.download(
|
||||
'/iot/tSimCardBindPkg/addPackage/excel/template',
|
||||
{
|
||||
responseReturn: 'raw',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageExcelSubmit(
|
||||
params: TSimBindPackageAddPackageExcelSubmitParam,
|
||||
): Promise<TSimBindPackageAddPackageSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardBindPkg/addPackage/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
manualConfirm: params.manualConfirm,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageOptions(params: {
|
||||
iccids: string[];
|
||||
}): Promise<TSimAddPackageOptionsRes> {
|
||||
return requestClient.post('/iot/tSimCardBindPkg/addPackage/options', params);
|
||||
}
|
||||
|
||||
export function AddPackagePaymentContext(): Promise<TSimAddPackageOptionsRes> {
|
||||
return requestClient.post('/iot/tSimCardBindPkg/addPackage/payment-context');
|
||||
}
|
||||
|
||||
export function AddPackageInputSubmit(
|
||||
params: TSimBindPackageAddPackageInputSubmitParam,
|
||||
): Promise<TSimBindPackageAddPackageSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardBindPkg/addPackage/input/submit', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
export function AddPackageInputPrepare(
|
||||
params: TSimBindPackageAddPackageInputPrepareParam,
|
||||
): Promise<TSimBindPackageAddPackageInputPrepareRes> {
|
||||
return requestClient.post('/iot/tSimCardBindPkg/addPackage/input/prepare', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
export function AddPackagePrepareResult(
|
||||
batchNo: string,
|
||||
): Promise<TSimAddPackagePrepareResult> {
|
||||
return requestClient.get('/iot/tSimCardBindPkg/addPackage/prepare/result', {
|
||||
params: { batchNo },
|
||||
});
|
||||
}
|
||||
|
||||
export function AddPackageBatchConfirm(
|
||||
params: TSimAddPackageBatchConfirmParam,
|
||||
): Promise<TSimAddPackageBatchConfirmRes> {
|
||||
return requestClient.post('/iot/tSimCardBindPkg/addPackage/batch/confirm', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
export type AddPackageEffectiveMode = 'current_month';
|
||||
export type AddPackagePaymentMode = 'balance' | 'offline';
|
||||
|
||||
export interface TSimBindPackageAddPackageExcelSubmitParam {
|
||||
file: File;
|
||||
paymentMode?: AddPackagePaymentMode;
|
||||
offlineContractCompleted?: boolean;
|
||||
manualConfirm?: boolean;
|
||||
}
|
||||
|
||||
export interface TSimBindPackageAddPackageInputSubmitParam {
|
||||
input: string;
|
||||
packageCode?: string;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
remark?: string;
|
||||
paymentMode?: AddPackagePaymentMode;
|
||||
offlineContractCompleted?: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimBindPackageAddPackageInputPrepareParam {
|
||||
input: string;
|
||||
packageCode?: string;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimBindPackageAddPackageSubmitRes {
|
||||
batchAsyncStatus?: number;
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
targetBatchType?: number;
|
||||
total?: number;
|
||||
validCount?: number;
|
||||
failCount?: number;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type TSimBindPackageAddPackageInputPrepareRes =
|
||||
TSimAddPackagePrepareResult;
|
||||
|
||||
export interface TSimAddPackageBatchConfirmParam {
|
||||
batchNo: string;
|
||||
packageCode?: string;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
remark?: string;
|
||||
paymentMode?: AddPackagePaymentMode | string;
|
||||
offlineContractCompleted?: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimAddPackageBatchConfirmRes {
|
||||
batchAsyncStatus?: number;
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
packageCode?: string;
|
||||
status?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimAddPackagePaymentAccount {
|
||||
payerDeptId: number;
|
||||
targetCount: number;
|
||||
requiredAmount: number | string;
|
||||
availableBalance: number | string;
|
||||
balanceEnough: boolean;
|
||||
}
|
||||
|
||||
export interface TSimAddPackageOption {
|
||||
flowMb: number;
|
||||
packageCode: string;
|
||||
packageName: string;
|
||||
unitPrice?: number | string;
|
||||
totalAmount?: number | string;
|
||||
priceAvailable?: boolean;
|
||||
priceReason?: string;
|
||||
paymentAccounts?: TSimAddPackagePaymentAccount[];
|
||||
}
|
||||
|
||||
export interface TSimAddPackageOptionsRes {
|
||||
items: TSimAddPackageOption[];
|
||||
isTopDept?: boolean;
|
||||
defaultPaymentMode?: AddPackagePaymentMode | string;
|
||||
availableBalance?: number | string;
|
||||
}
|
||||
|
||||
export interface TSimAddPackagePrepareResult {
|
||||
availableBalance?: number | string;
|
||||
batchAsyncStatus?: number;
|
||||
batchInfo?: Record<string, any>;
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
effectiveModeText?: string;
|
||||
effectiveTime?: string;
|
||||
expectedExpireTime?: string;
|
||||
failCount?: number;
|
||||
failReason?: string;
|
||||
flowMb?: number | string;
|
||||
isTopDept?: boolean;
|
||||
packageCode?: string;
|
||||
packageName?: string;
|
||||
paymentAccounts?: TSimAddPackagePaymentAccount[];
|
||||
availablePackages?: TSimAddPackageOption[];
|
||||
quantity?: number;
|
||||
runResult?: number;
|
||||
snapshot?: Record<string, any>;
|
||||
status?: string;
|
||||
successCount?: number;
|
||||
targetBatchType?: number;
|
||||
total?: number;
|
||||
totalAmount?: number | string;
|
||||
unitPrice?: number | string;
|
||||
validCount?: number;
|
||||
defaultPaymentMode?: AddPackagePaymentMode | string;
|
||||
[property: string]: any;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import type {
|
||||
TSimCardCancelExcelSubmitParam,
|
||||
TSimCardCancelInputSubmitParam,
|
||||
TSimCardCancelSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardCancel/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardCancelExcelSubmitParam,
|
||||
): Promise<TSimCardCancelSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardCancel/excel/submit',
|
||||
{ file: params.file },
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardCancelInputSubmitParam,
|
||||
): Promise<TSimCardCancelSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardCancel/input/submit', params);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/** 提交Excel卡销户请求参数 */
|
||||
export interface TSimCardCancelExcelSubmitParam {
|
||||
/** Excel文件 */
|
||||
file: File;
|
||||
}
|
||||
|
||||
/** 提交批量输入卡销户请求参数 */
|
||||
export interface TSimCardCancelInputSubmitParam {
|
||||
/** 批量输入ICCID文本 */
|
||||
input: string;
|
||||
/** 销户备注 */
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
/** 卡销户提交响应 */
|
||||
export interface TSimCardCancelSubmitRes {
|
||||
/** 批次异步处理状态(Pending 等) */
|
||||
batchAsyncStatus?: number;
|
||||
/** 批次号 */
|
||||
batchNo?: string;
|
||||
/** 批次类型 */
|
||||
batchType?: number;
|
||||
/** 失败行数 */
|
||||
failCount?: number;
|
||||
/** 实际销户数量 */
|
||||
quantity?: number;
|
||||
/** 结果下载任务ID */
|
||||
resultDownloadId?: number;
|
||||
/** 结果文件OSS ID */
|
||||
resultFileOssId?: number;
|
||||
/** 导入状态 */
|
||||
status?: string;
|
||||
/** 解析总行数 */
|
||||
total?: number;
|
||||
/** 校验通过行数 */
|
||||
validCount?: number;
|
||||
[property: string]: any;
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const get = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
get,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardChange api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
get.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads excel change template from backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardChange/excel/template',
|
||||
{
|
||||
responseReturn: 'raw',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('submits excel change as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'change.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardChange/excel/submit',
|
||||
{ file },
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('prepares input change with backend contract path', async () => {
|
||||
const { InputPrepare } = await import('./index');
|
||||
const params = {
|
||||
durationMonths: 6,
|
||||
effectiveMode: 'immediate' as const,
|
||||
input: '8986000000000000001\n8986000000000000002',
|
||||
newPackageCode: 'PKG002',
|
||||
offlineContractCompleted: true,
|
||||
};
|
||||
|
||||
InputPrepare(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardChange/input/prepare', {
|
||||
...params,
|
||||
});
|
||||
});
|
||||
|
||||
it('prepares range change with backend contract path', async () => {
|
||||
const { RangePrepare } = await import('./index');
|
||||
const params = {
|
||||
durationMonths: 6,
|
||||
effectiveMode: 'next_month' as const,
|
||||
endIccid: '8986000000000000009',
|
||||
endImsi: '460000000000009',
|
||||
endMsisdn: '13000000009',
|
||||
newPackageCode: 'PKG002',
|
||||
offlineContractCompleted: true,
|
||||
startIccid: '8986000000000000001',
|
||||
startImsi: '460000000000001',
|
||||
startMsisdn: '13000000001',
|
||||
};
|
||||
|
||||
RangePrepare(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardChange/range/prepare', {
|
||||
...params,
|
||||
});
|
||||
});
|
||||
|
||||
it('submits change prepare batch with backend contract path', async () => {
|
||||
const { BatchSubmit } = await import('./index');
|
||||
const params = {
|
||||
batchNo: 'CH202607060001',
|
||||
durationMonths: 6,
|
||||
effectiveMode: 'immediate' as const,
|
||||
newPackageCode: 'PKG002',
|
||||
offlineContractCompleted: true,
|
||||
};
|
||||
|
||||
BatchSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardChange/batch/submit', {
|
||||
...params,
|
||||
});
|
||||
});
|
||||
|
||||
it('polls change prepare result with backend contract path', async () => {
|
||||
const { PrepareResult } = await import('./index');
|
||||
const batchNo = 'CH202607060001';
|
||||
|
||||
PrepareResult(batchNo);
|
||||
|
||||
expect(get).toHaveBeenCalledWith('/iot/tSimCardChange/prepare/result', {
|
||||
params: { batchNo },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
import type {
|
||||
TSimCardChangeBatchPrepareRes,
|
||||
TSimCardChangeBatchPrepareResult,
|
||||
TSimCardChangeBatchSubmitParam,
|
||||
TSimCardChangeBatchSubmitRes,
|
||||
TSimCardChangeExcelSubmitParam,
|
||||
TSimCardChangeExcelSubmitRes,
|
||||
TSimCardChangeInputPrepareParam,
|
||||
TSimCardChangeInputOptionsParam,
|
||||
TSimCardChangeOptionsRes,
|
||||
TSimCardChangeRangePrepareParam,
|
||||
TSimCardChangeRangeOptionsParam,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardChange/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardChangeExcelSubmitParam,
|
||||
): Promise<TSimCardChangeExcelSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardChange/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputOptions(params: TSimCardChangeInputOptionsParam) {
|
||||
return requestClient.post<TSimCardChangeOptionsRes>(
|
||||
'/iot/tSimCardChange/input/change-options',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
export function RangeOptions(params: TSimCardChangeRangeOptionsParam) {
|
||||
return requestClient.post<TSimCardChangeOptionsRes>(
|
||||
'/iot/tSimCardChange/range/change-options',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
export function InputPrepare(params: TSimCardChangeInputPrepareParam) {
|
||||
return requestClient.post<TSimCardChangeBatchPrepareRes>(
|
||||
'/iot/tSimCardChange/input/prepare',
|
||||
{ ...params },
|
||||
);
|
||||
}
|
||||
|
||||
export function RangePrepare(params: TSimCardChangeRangePrepareParam) {
|
||||
return requestClient.post<TSimCardChangeBatchPrepareRes>(
|
||||
'/iot/tSimCardChange/range/prepare',
|
||||
{ ...params },
|
||||
);
|
||||
}
|
||||
|
||||
export function BatchSubmit(params: TSimCardChangeBatchSubmitParam) {
|
||||
return requestClient.post<TSimCardChangeBatchSubmitRes>(
|
||||
'/iot/tSimCardChange/batch/submit',
|
||||
{ ...params },
|
||||
);
|
||||
}
|
||||
|
||||
export function PrepareResult(batchNo: string) {
|
||||
return requestClient.get<TSimCardChangeBatchPrepareResult>(
|
||||
'/iot/tSimCardChange/prepare/result',
|
||||
{ params: { batchNo } },
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
export type TSimCardChangeEffectiveMode = 'immediate' | 'next_month';
|
||||
|
||||
export interface TSimCardChangeInputPrepareParam {
|
||||
durationMonths: number;
|
||||
effectiveMode: TSimCardChangeEffectiveMode;
|
||||
giftDurationMonths?: number;
|
||||
input: string;
|
||||
newPackageCode: string;
|
||||
offlineContractCompleted: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeExcelSubmitParam {
|
||||
file: File;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeExcelSubmitRes {
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
resultDownloadId?: number;
|
||||
resultFileOssId?: number;
|
||||
status?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeInputOptionsParam {
|
||||
input: string;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeRangeOptionsParam {
|
||||
endIccid: string;
|
||||
endImsi: string;
|
||||
endMsisdn: string;
|
||||
startIccid: string;
|
||||
startImsi: string;
|
||||
startMsisdn: string;
|
||||
}
|
||||
|
||||
export interface TSimCardChangePackageOption {
|
||||
changeUnitPrice?: number | string;
|
||||
flowMb?: number;
|
||||
packageCode: string;
|
||||
packageName: string;
|
||||
packageType?: number;
|
||||
renewableDurationOptions?: number[];
|
||||
}
|
||||
|
||||
export interface TSimCardChangeOptionsRes {
|
||||
customerAgentId?: number;
|
||||
customerName?: string;
|
||||
oldPackageCode?: string;
|
||||
oldPackageName?: string;
|
||||
oldPackageType?: number;
|
||||
packages?: TSimCardChangePackageOption[];
|
||||
quantity?: number;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeBatchPrepareRes {
|
||||
batchNo: string;
|
||||
batchType?: number;
|
||||
agentDefaultPriceId?: number;
|
||||
changeUnitPrice?: number | string;
|
||||
customerAgentId?: number;
|
||||
customerName?: string;
|
||||
failCount?: number;
|
||||
newPackageCode?: string;
|
||||
newPackageFlowMb?: number;
|
||||
newPackageName?: string;
|
||||
newPackageType?: number;
|
||||
oldPackageCode?: string;
|
||||
oldPackageFlowMb?: number;
|
||||
oldPackageName?: string;
|
||||
oldPackageType?: number;
|
||||
priceSource?: string;
|
||||
quantity?: number;
|
||||
renewableDurationOptions?: number[];
|
||||
resultDownloadId?: number;
|
||||
resultFileOssId?: number;
|
||||
sourceBatchNo?: string;
|
||||
status?: string;
|
||||
targetBatchType?: number;
|
||||
targetPriceId?: number;
|
||||
total?: number;
|
||||
validCount?: number;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeRangePrepareParam {
|
||||
durationMonths: number;
|
||||
effectiveMode: TSimCardChangeEffectiveMode;
|
||||
endIccid: string;
|
||||
endImsi: string;
|
||||
endMsisdn: string;
|
||||
giftDurationMonths?: number;
|
||||
newPackageCode: string;
|
||||
offlineContractCompleted: boolean;
|
||||
startIccid: string;
|
||||
startImsi: string;
|
||||
startMsisdn: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeBatchSubmitParam {
|
||||
adminNote?: string;
|
||||
batchNo: string;
|
||||
buyerNote?: string;
|
||||
durationMonths: number;
|
||||
effectiveMode: TSimCardChangeEffectiveMode;
|
||||
giftDurationMonths?: number;
|
||||
newPackageCode: string;
|
||||
offlineContractCompleted: boolean;
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardChangeBatchSubmitRes {
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
changeUnitPrice?: number | string;
|
||||
customerAgentId?: number;
|
||||
customerName?: string;
|
||||
durationMonths?: number;
|
||||
effectiveMode?: string;
|
||||
giftDurationMonths?: number;
|
||||
newPackageCode?: string;
|
||||
newPackageName?: string;
|
||||
oldPackageCode?: string;
|
||||
oldPackageName?: string;
|
||||
orderSn?: string;
|
||||
packageBeginTime?: string;
|
||||
packageEndTime?: string;
|
||||
quantity?: number;
|
||||
sourceBatchNo?: string;
|
||||
status?: string;
|
||||
totalAmount?: number | string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type TSimCardChangeBatchAsyncStatus = number;
|
||||
|
||||
export interface TSimCardChangeBatchPrepareResult {
|
||||
batchAsyncStatus: TSimCardChangeBatchAsyncStatus;
|
||||
batchInfo?: TSimCardChangeBatchPrepareRes;
|
||||
batchNo: string;
|
||||
failReason?: string;
|
||||
runResult?: number;
|
||||
status: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardDataCut api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the data cut template from the backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardDataCut/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits an excel data cut batch with the batch threshold', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'dataCut.xlsx');
|
||||
|
||||
ExcelSubmit({ file, trafficCutoffThreshold: 1024.125 });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardDataCut/excel/submit',
|
||||
{ file, trafficCutoffThreshold: 1024.125 },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input data cut batch from the backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001',
|
||||
trafficCutoffThreshold: 2048,
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardDataCut/input/submit', params);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import type {
|
||||
TSimCardDataCutExcelSubmitParam,
|
||||
TSimCardDataCutInputSubmitParam,
|
||||
TSimCardDataCutSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardDataCut/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardDataCutExcelSubmitParam,
|
||||
): Promise<TSimCardDataCutSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardDataCut/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
trafficCutoffThreshold: params.trafficCutoffThreshold,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardDataCutInputSubmitParam,
|
||||
): Promise<TSimCardDataCutSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardDataCut/input/submit', params);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export interface TSimCardDataCutExcelSubmitParam {
|
||||
file: File;
|
||||
trafficCutoffThreshold: number;
|
||||
}
|
||||
|
||||
export interface TSimCardDataCutInputSubmitParam {
|
||||
input: string;
|
||||
trafficCutoffThreshold: number;
|
||||
}
|
||||
|
||||
export interface TSimCardDataCutSubmitRes {
|
||||
batchNo: string;
|
||||
batchType: number;
|
||||
batchAsyncStatus: number;
|
||||
total: number;
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardDataStart api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the data start template from the backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardDataStart/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits an excel data start batch as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'dataStart.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardDataStart/excel/submit',
|
||||
{ file },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input data start batch from the backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001',
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardDataStart/input/submit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import type {
|
||||
TSimCardLifecycleExcelSubmitParam,
|
||||
TSimCardLifecycleInputSubmitParam,
|
||||
TSimCardLifecycleSubmitRes,
|
||||
} from '../tSimCardLifecycle/type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardDataStart/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardLifecycleExcelSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardDataStart/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardLifecycleInputSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardDataStart/input/submit', params);
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardDataStop api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the data stop template from the backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardDataStop/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits an excel data stop batch as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'dataStop.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardDataStop/excel/submit',
|
||||
{ file },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input data stop batch from the backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001 14000000001 460001000000001',
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardDataStop/input/submit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import type {
|
||||
TSimCardLifecycleExcelSubmitParam,
|
||||
TSimCardLifecycleInputSubmitParam,
|
||||
TSimCardLifecycleSubmitRes,
|
||||
} from '../tSimCardLifecycle/type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardDataStop/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardLifecycleExcelSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardDataStop/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardLifecycleInputSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardDataStop/input/submit', params);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const get = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
get,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardInfo session api', () => {
|
||||
beforeEach(() => {
|
||||
get.mockReset();
|
||||
});
|
||||
|
||||
it('queries session without showing a global failure message', async () => {
|
||||
const { QuerySimSession } = await import('./index');
|
||||
const params = { iccid: '8986000000000000001' };
|
||||
|
||||
QuerySimSession(params);
|
||||
|
||||
expect(get).toHaveBeenCalledWith('iot/tSimCardInfo/querySimSession', {
|
||||
params,
|
||||
errorMessageMode: 'none',
|
||||
});
|
||||
});
|
||||
|
||||
it('queries status without showing a global failure message', async () => {
|
||||
const { QuerySimStatus } = await import('./index');
|
||||
const params = { iccid: '8986000000000000001' };
|
||||
|
||||
QuerySimStatus(params);
|
||||
|
||||
expect(get).toHaveBeenCalledWith('iot/tSimCardInfo/querySimStatus', {
|
||||
params,
|
||||
errorMessageMode: 'none',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 获取卡信息表列表
|
||||
export function List(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardInfo/list', { params });
|
||||
}
|
||||
|
||||
// 批量号码查询使用 POST,避免较长号码列表超过 URL 长度限制
|
||||
export function BatchList(params: any) {
|
||||
return requestClient.post<any>('iot/tSimCardInfo/list', { ...params });
|
||||
}
|
||||
|
||||
// 删除/批量删除卡信息表
|
||||
export function Delete(params: any) {
|
||||
return requestClient.post<any>('iot/tSimCardInfo/delete', { ...params });
|
||||
}
|
||||
|
||||
// 添加/编辑卡信息表
|
||||
export function Edit(params: any) {
|
||||
return requestClient.post<any>('iot/tSimCardInfo/edit', { ...params });
|
||||
}
|
||||
|
||||
// 获取卡信息表指定详情
|
||||
export function View(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardInfo/view', { params });
|
||||
}
|
||||
|
||||
// 导出卡信息表
|
||||
export function Export(params: any) {
|
||||
return requestClient.post<Blob>(
|
||||
'/iot/tSimCardInfo/export',
|
||||
{ ...params },
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
},
|
||||
responseType: 'blob',
|
||||
},
|
||||
);
|
||||
}
|
||||
// 同步单张SIM卡用量
|
||||
export function SyncSimCardFlow(params: any) {
|
||||
return requestClient.post<any>('iot/tSimCardInfo/syncSimCardFlow', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
// 同步SIM卡状态
|
||||
export function SyncSimCardStatus(params: any) {
|
||||
return requestClient.post<any>('iot/tSimCardInfo/syncSimCardStatus', {
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
// // 查询SIM卡会话
|
||||
// export function QuerySimSession(params: TSimCardInfoQuerySimSessionParam) {
|
||||
// return requestClient.get<TSimCardInfoQuerySimSessionRes>(
|
||||
// 'iot/tSimCardInfo/querySimSession',
|
||||
// { params },
|
||||
// );
|
||||
// }
|
||||
// 查询SIM卡会话
|
||||
export function QuerySimSession(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardInfo/querySimSession', {
|
||||
params,
|
||||
errorMessageMode: 'none',
|
||||
});
|
||||
}
|
||||
|
||||
// 查询SIM卡状态
|
||||
export function QuerySimStatus(params: any) {
|
||||
return requestClient.get<any>('iot/tSimCardInfo/querySimStatus', {
|
||||
params,
|
||||
errorMessageMode: 'none',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
import type { GlobalListRes } from '#/types/global';
|
||||
import type { MemberSumma } from '#/utils';
|
||||
|
||||
/** 卡信息表列表项 */
|
||||
export interface TSimCardInfoModel {
|
||||
/** 主键ID */
|
||||
id: number;
|
||||
/** ICCID */
|
||||
iccid: string;
|
||||
/** MSISDN/卡号 */
|
||||
msisdn: string;
|
||||
/** IMSI */
|
||||
imsi: string;
|
||||
/** IMEI */
|
||||
imei: string;
|
||||
/** 归属地 */
|
||||
regionCode: string;
|
||||
/** 渠道客户ID */
|
||||
deptId: number;
|
||||
/** 渠道客户名称 */
|
||||
deptName: string;
|
||||
/** 当前套餐编号 */
|
||||
currentPackageCode: string;
|
||||
/** 当前套餐名称 */
|
||||
packageName: string;
|
||||
/** 套餐状态:0 无套餐,1待生效,2生效中,3已过期 */
|
||||
packageStatus: number;
|
||||
/** 接入方式:ipv4、ipv6、ipv4_ipv6 */
|
||||
accessType: number;
|
||||
/** 运营商卡状态 枚举 */
|
||||
bossCardStatus: number;
|
||||
/** 卡类型 枚举 */
|
||||
cardType: number;
|
||||
/** 运营商开户日期 */
|
||||
bossOpenAt: string;
|
||||
/** 运营商激活日期 */
|
||||
bossActivateAt: string;
|
||||
/** 是否按运营商激活减去赠送时长方:1是,0否 */
|
||||
isBossActivateEnabled: number;
|
||||
/** 入库批次 */
|
||||
inboundBatchNo: string;
|
||||
/** 出库批次 */
|
||||
outboundBatchNo: string;
|
||||
/** 划拨批次 */
|
||||
allocationBatchNo: string;
|
||||
/** 是否为池卡:1是,0否 */
|
||||
isFlowPool: number;
|
||||
/** 流量池编号 */
|
||||
flowPoolCode: string;
|
||||
/** 当前套餐生效时间 */
|
||||
flowPkgBeginAt: string;
|
||||
/** 套餐赠送结束时间 */
|
||||
flowPkgPresentAt: string;
|
||||
/** 实际赠送结束时间 */
|
||||
flowPkgRealPresentAt: string;
|
||||
/** 当前套餐预计到期时间 */
|
||||
flowPkgEndAt: string;
|
||||
/** 数据服务状态:1启用、0禁用 */
|
||||
dataServiceStatus: number;
|
||||
/** 套餐总流量MB */
|
||||
packageTotalFlowMb: number;
|
||||
/** 已用流量MB */
|
||||
usedFlowMb: number;
|
||||
/** 达量断网配置状态(0未配置 1已开启 2已关闭) */
|
||||
trafficCutoffStatus: number;
|
||||
/** 达量断网阈值 */
|
||||
trafficCutoffThreshold: number;
|
||||
/** 短信服务状态:1启用、0禁用 */
|
||||
smsServiceStatus: number;
|
||||
/** 套餐短信总条数 */
|
||||
packageTotalSms: number;
|
||||
/** 已用短信条数 */
|
||||
usedSms: number;
|
||||
/** 语音服务状态:1启用、0禁用 */
|
||||
voiceServiceStatus: number;
|
||||
/** 套餐语音总分钟数 */
|
||||
packageTotalVoice: number;
|
||||
/** 已用语音分钟数 */
|
||||
usedVoice: number;
|
||||
/** 国漫服务状态:1启用、0禁用 */
|
||||
roamServiceStatus: number;
|
||||
/** 套餐国际流量MB */
|
||||
packageTotalRoamFlowMb: number;
|
||||
/** 已用国际流量MB */
|
||||
usedRoamFlowMb: number;
|
||||
/** 状态最后一次同步时间 */
|
||||
statusSyncTime: string;
|
||||
/** 流量最后一次同步时间 */
|
||||
flowSyncTime: string;
|
||||
/** 短信最后一次同步时间 */
|
||||
smsSyncTime: string;
|
||||
/** 语音最后一次同步时间 */
|
||||
voiceSyncTime: string;
|
||||
/** 国漫最后一次同步时间 */
|
||||
roamSyncTime: string;
|
||||
/** 是否收取附加费:1是,0否 */
|
||||
extraFeeEnabled: number;
|
||||
/** 附加费用倍数 */
|
||||
extraFeeMultiple: number;
|
||||
/** 附加金额 */
|
||||
extraFee: number;
|
||||
/** 通道编号 */
|
||||
chanKey: string;
|
||||
/** 通道名称 */
|
||||
chanName: string;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 网络类型:4G、5G、NB-IoT */
|
||||
netModel: number;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/** 获取卡信息表指定信息响应项 */
|
||||
export interface TSimCardInfoViewModel {
|
||||
/** 通道名称 */
|
||||
chanName: string;
|
||||
/** 部门名称 */
|
||||
deptName: string;
|
||||
/** 套餐名称 */
|
||||
packageName: string;
|
||||
/** 剩余流量MB */
|
||||
reminFlowMb: number;
|
||||
/** 主键ID */
|
||||
id: number;
|
||||
/** ICCID */
|
||||
iccid: string;
|
||||
/** MSISDN/卡号 */
|
||||
msisdn: string;
|
||||
/** IMSI */
|
||||
imsi: string;
|
||||
/** IMEI */
|
||||
imei: string;
|
||||
/** 归属地 */
|
||||
regionCode: string;
|
||||
/** 渠道客户ID */
|
||||
deptId: number;
|
||||
/** 当前套餐编号 */
|
||||
currentPackageCode: string;
|
||||
/** 套餐状态:0 无套餐,1待生效,2生效中,3已过期 */
|
||||
packageStatus: number;
|
||||
/** 接入方式:ipv4、ipv6、ipv4_ipv6 */
|
||||
accessType: number;
|
||||
/** 运营商卡状态 枚举 */
|
||||
bossCardStatus: number;
|
||||
/** 卡类型 枚举 */
|
||||
cardType: number;
|
||||
/** 运营商开户日期 */
|
||||
bossOpenAt: string;
|
||||
/** 运营商激活日期 */
|
||||
bossActivateAt: string;
|
||||
/** 是否按运营商激活减去赠送时长方:1是,0否 */
|
||||
isBossActivateEnabled: number;
|
||||
/** 入库批次 */
|
||||
inboundBatchNo: string;
|
||||
/** 出库批次 */
|
||||
outboundBatchNo: string;
|
||||
/** 划拨批次 */
|
||||
allocationBatchNo: string;
|
||||
/** 是否为池卡:1是,0否 */
|
||||
isFlowPool: number;
|
||||
/** 流量池编号 */
|
||||
flowPoolCode: string;
|
||||
/** 当前套餐生效时间 */
|
||||
flowPkgBeginAt: string;
|
||||
/** 套餐赠送结束时间 */
|
||||
flowPkgPresentAt: string;
|
||||
/** 实际赠送结束时间 */
|
||||
flowPkgRealPresentAt: string;
|
||||
/** 当前套餐预计到期时间 */
|
||||
flowPkgEndAt: string;
|
||||
/** 数据服务状态:1启用、0禁用 */
|
||||
dataServiceStatus: number;
|
||||
/** 套餐总流量MB */
|
||||
packageTotalFlowMb: number;
|
||||
/** 已用流量MB */
|
||||
usedFlowMb: number;
|
||||
/** 达量断网配置状态(0未配置 1已开启 2已关闭) */
|
||||
trafficCutoffStatus: number;
|
||||
/** 达量断网阈值 */
|
||||
trafficCutoffThreshold: number;
|
||||
/** 短信服务状态:1启用、0禁用 */
|
||||
smsServiceStatus: number;
|
||||
/** 套餐短信总条数 */
|
||||
packageTotalSms: number;
|
||||
/** 已用短信条数 */
|
||||
usedSms: number;
|
||||
/** 语音服务状态:1启用、0禁用 */
|
||||
voiceServiceStatus: number;
|
||||
/** 套餐语音总分钟数 */
|
||||
packageTotalVoice: number;
|
||||
/** 已用语音分钟数 */
|
||||
usedVoice: number;
|
||||
/** 国漫服务状态:1启用、0禁用 */
|
||||
roamServiceStatus: number;
|
||||
/** 套餐国际流量MB */
|
||||
packageTotalRoamFlowMb: number;
|
||||
/** 已用国际流量MB */
|
||||
usedRoamFlowMb: number;
|
||||
/** 状态最后一次同步时间 */
|
||||
statusSyncTime: string;
|
||||
/** 流量最后一次同步时间 */
|
||||
flowSyncTime: string;
|
||||
/** 短信最后一次同步时间 */
|
||||
smsSyncTime: string;
|
||||
/** 语音最后一次同步时间 */
|
||||
voiceSyncTime: string;
|
||||
/** 国漫最后一次同步时间 */
|
||||
roamSyncTime: string;
|
||||
/** 是否收取附加费:1是,0否 */
|
||||
extraFeeEnabled: number;
|
||||
/** 附加费用倍数 */
|
||||
extraFeeMultiple: number;
|
||||
/** 附加金额 */
|
||||
extraFee: number;
|
||||
/** 通道编号 */
|
||||
chanKey: string;
|
||||
/** 网络类型:4G、5G、NB-IoT */
|
||||
netModel: number;
|
||||
/** 备注 */
|
||||
remark: string;
|
||||
/** 租户ID */
|
||||
tenantId: string;
|
||||
/** 创建部门 */
|
||||
createdDept: number;
|
||||
/** 创建者 */
|
||||
createdBy: number;
|
||||
/** 创建时间 */
|
||||
createdAt: string;
|
||||
/** 更新者 */
|
||||
updatedBy: number;
|
||||
/** 更新时间 */
|
||||
updatedAt: string;
|
||||
/** 创建者摘要信息 */
|
||||
createdBySumma: MemberSumma;
|
||||
/** 更新者摘要信息 */
|
||||
updatedBySumma: MemberSumma;
|
||||
}
|
||||
|
||||
/** 获取卡信息表列表 请求参数 */
|
||||
export interface TSimCardInfoListParam {
|
||||
/** 页码 */
|
||||
page?: number;
|
||||
/** 每页大小 */
|
||||
pageSize?: number;
|
||||
/** 关键字 */
|
||||
keyword?: string;
|
||||
/** 运营商卡状态 */
|
||||
bossCardStatus?: number;
|
||||
/** 时间类型 */
|
||||
timeType?: number;
|
||||
/** 时间段 */
|
||||
time?: string[];
|
||||
/** 查询条件 */
|
||||
condition?: string;
|
||||
/** 起始号段 */
|
||||
startNum?: string;
|
||||
/** 结束号段 */
|
||||
endNum?: string;
|
||||
/** 维度 */
|
||||
dimension?: number;
|
||||
/** 维度状态 */
|
||||
dimensionStatus?: string;
|
||||
/** 维度值 */
|
||||
dimensionValue?: string;
|
||||
/** 排序值 */
|
||||
sortValue?: number;
|
||||
/** 排序类型 */
|
||||
sortType?: number;
|
||||
/** 通道编号 */
|
||||
chanKey?: string;
|
||||
/** 当前套餐编码 */
|
||||
currentPackageCode?: string;
|
||||
/** 卡号 */
|
||||
cardValue?: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** IMEI */
|
||||
imei?: string;
|
||||
/** 渠道客户ID */
|
||||
deptId?: number;
|
||||
/** 主键ID */
|
||||
id?: number;
|
||||
/** ICCID */
|
||||
iccid?: string;
|
||||
/** MSISDN/卡号 */
|
||||
msisdn?: string;
|
||||
/** IMSI */
|
||||
imsi?: string;
|
||||
/** 套餐状态:0 无套餐,1待生效,2生效中,3已过期 */
|
||||
packageStatus?: number;
|
||||
/** 数据服务状态:1启用、0禁用 */
|
||||
dataServiceStatus?: number;
|
||||
/** 短信服务状态:1启用、0禁用 */
|
||||
smsServiceStatus?: number;
|
||||
/** 语音服务状态:1启用、0禁用 */
|
||||
voiceServiceStatus?: number;
|
||||
/** 国漫服务状态:1启用、0禁用 */
|
||||
roamServiceStatus?: number;
|
||||
/** 创建时间 */
|
||||
createdAt?: string[];
|
||||
}
|
||||
|
||||
/** 获取卡信息表列表 响应 */
|
||||
export type TSimCardInfoListRes = GlobalListRes<TSimCardInfoModel>;
|
||||
|
||||
/** 导出卡信息表列表 请求参数 */
|
||||
export type TSimCardInfoExportParam = TSimCardInfoListParam;
|
||||
|
||||
/** 修改/新增卡信息表 请求参数 */
|
||||
export interface TSimCardInfoEditParam {
|
||||
/** 主键ID */
|
||||
id?: number;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/** 获取卡信息表指定信息 请求参数 */
|
||||
export interface TSimCardInfoViewParam {
|
||||
/** 主键ID */
|
||||
id?: number;
|
||||
/** ICCID */
|
||||
iccid?: string;
|
||||
/** MSISDN/卡号 */
|
||||
msisdn?: string;
|
||||
}
|
||||
|
||||
/** 获取卡信息表指定信息 响应 */
|
||||
export type TSimCardInfoViewRes = TSimCardInfoViewModel;
|
||||
|
||||
/** 删除卡信息表 请求参数 */
|
||||
export interface TSimCardInfoDeleteParam {
|
||||
/** 主键ID */
|
||||
id: number | number[];
|
||||
}
|
||||
|
||||
/** 查询SIM卡会话 请求参数 */
|
||||
export interface TSimCardInfoQuerySimSessionParam {
|
||||
/** ICCID */
|
||||
iccid: string;
|
||||
}
|
||||
|
||||
/** 查询SIM卡会话 响应项 */
|
||||
export interface TSimCardInfoQuerySimSessionModel {
|
||||
/** APN */
|
||||
apnId: string;
|
||||
/** 实时IMEI */
|
||||
imei?: string;
|
||||
/** 接入方式 */
|
||||
rat: string;
|
||||
/** IPv4地址 */
|
||||
ipv4: string;
|
||||
/** IPv6地址 */
|
||||
ipv6: string;
|
||||
/** IPv6前缀 */
|
||||
ipv6Prefix: string;
|
||||
/** 在线状态 */
|
||||
status: string;
|
||||
/** 会话创建时间 */
|
||||
createTime: string;
|
||||
}
|
||||
|
||||
/** 查询SIM卡会话 响应 */
|
||||
export type TSimCardInfoQuerySimSessionRes =
|
||||
null | TSimCardInfoQuerySimSessionModel;
|
||||
|
||||
/** 查询SIM卡状态 请求参数 */
|
||||
export type TSimCardInfoQuerySimStatusParam =
|
||||
TSimCardInfoQuerySimSessionParam;
|
||||
|
||||
/** 查询SIM卡状态 响应项 */
|
||||
export interface TSimCardInfoQuerySimStatusModel {
|
||||
/** 卡状态 */
|
||||
cardStatus?: number;
|
||||
/** 最后变更时间 */
|
||||
lastChangeDate?: string;
|
||||
}
|
||||
|
||||
/** 查询SIM卡状态 响应 */
|
||||
export type TSimCardInfoQuerySimStatusRes =
|
||||
null | TSimCardInfoQuerySimStatusModel;
|
||||
@@ -0,0 +1,20 @@
|
||||
export interface TSimCardLifecycleExcelSubmitParam {
|
||||
/** Excel 文件 */
|
||||
file: File;
|
||||
}
|
||||
|
||||
export interface TSimCardLifecycleInputSubmitParam {
|
||||
/** 每行填写 ICCID,或 ICCID MSISDN IMSI */
|
||||
input: string;
|
||||
}
|
||||
|
||||
export interface TSimCardLifecycleSubmitRes {
|
||||
/** 批次编号 */
|
||||
batchNo: string;
|
||||
/** 批次类型 */
|
||||
batchType: number;
|
||||
/** 异步处理状态 */
|
||||
batchAsyncStatus: number;
|
||||
/** 提交总行数 */
|
||||
total: number;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import type {
|
||||
ExportColumn,
|
||||
SimCardQueryExportParam,
|
||||
SimCardQuerySubmitRes,
|
||||
SimCardUsageHistoryColumnsRes,
|
||||
SimCardUsageHistoryDeptOptionsRes,
|
||||
SimCardUsageHistoryExportParam,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
/** 卡基础信息查询:下载 Excel 模板 */
|
||||
export function DownloadBaseTemplate() {
|
||||
return requestClient.download('/iot/tSimCardBaseQuery/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
/** 卡基础信息查询:可选导出列 */
|
||||
export function BaseColumns(): Promise<{ items: ExportColumn[] }> {
|
||||
return requestClient.get('/iot/tSimCardBaseQuery/columns');
|
||||
}
|
||||
|
||||
/**
|
||||
* 两个导出接口共用的 multipart 组装。
|
||||
* 提交字段只在这里维护,避免 BaseExport / UsageExport 各写一份后口径漂移。
|
||||
*/
|
||||
function buildExportForm(params: SimCardQueryExportParam): FormData {
|
||||
const form = new FormData();
|
||||
form.append('mode', params.mode);
|
||||
form.append('exportColumnsJson', JSON.stringify(params.exportColumns ?? []));
|
||||
if (params.batchInput !== undefined) {
|
||||
form.append('batchInput', params.batchInput);
|
||||
}
|
||||
if (params.dimension !== undefined) {
|
||||
form.append('dimension', params.dimension);
|
||||
}
|
||||
if (params.startNum !== undefined) {
|
||||
form.append('startNum', params.startNum);
|
||||
}
|
||||
if (params.endNum !== undefined) {
|
||||
form.append('endNum', params.endNum);
|
||||
}
|
||||
return form;
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡基础信息查询:提交导出。
|
||||
* 统一走 multipart:Excel 模式带 file,其余模式只带表单字段,
|
||||
* 保持三个输入方式的请求路径一致。
|
||||
*/
|
||||
export function BaseExport(
|
||||
params: SimCardQueryExportParam & { file?: File },
|
||||
): Promise<SimCardQuerySubmitRes> {
|
||||
const form = buildExportForm(params);
|
||||
if (params.file) {
|
||||
form.append('file', params.file);
|
||||
}
|
||||
return requestClient.post('/iot/tSimCardBaseQuery/export', form, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
/** 月历史用量查询:下载 Excel 模板 */
|
||||
export function DownloadUsageTemplate() {
|
||||
return requestClient.download('/iot/tSimCardUsageHistory/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
/** 月历史用量查询:固定列与近12个月月份清单 */
|
||||
export function UsageColumns(): Promise<SimCardUsageHistoryColumnsRes> {
|
||||
return requestClient.get('/iot/tSimCardUsageHistory/columns');
|
||||
}
|
||||
|
||||
/** 月历史用量查询:可选公司,展示范围由数据权限决定 */
|
||||
export function UsageDeptOptions(): Promise<SimCardUsageHistoryDeptOptionsRes> {
|
||||
return requestClient.get('/iot/tSimCardUsageHistory/deptOptions');
|
||||
}
|
||||
|
||||
/** 月历史用量查询:提交导出 */
|
||||
export function UsageExport(
|
||||
params: SimCardUsageHistoryExportParam & { file?: File },
|
||||
): Promise<SimCardQuerySubmitRes> {
|
||||
// deptId 是 dept 模式的必填项,缺省时不能悄悄提交一个没有公司范围的导出请求。
|
||||
if (params.mode === 'dept' && !(Number(params.deptId) > 0)) {
|
||||
return Promise.reject(new Error('按所属公司查询时必须选择具体公司'));
|
||||
}
|
||||
const form = buildExportForm(params);
|
||||
if (params.deptId !== undefined && params.deptId > 0) {
|
||||
form.append('deptId', String(params.deptId));
|
||||
}
|
||||
if (params.expireStartTime) {
|
||||
form.append('expireStartTime', params.expireStartTime);
|
||||
}
|
||||
if (params.expireEndTime) {
|
||||
form.append('expireEndTime', params.expireEndTime);
|
||||
}
|
||||
if (params.file) {
|
||||
form.append('file', params.file);
|
||||
}
|
||||
return requestClient.post('/iot/tSimCardUsageHistory/export', form, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
export interface ExportColumn {
|
||||
/** 列表模型字段名,后端按它取值 */
|
||||
field: string;
|
||||
/** 表头文字 */
|
||||
label: string;
|
||||
dictType?: string;
|
||||
}
|
||||
|
||||
export type QueryMode = 'excel' | 'input' | 'range' | 'dept';
|
||||
|
||||
export interface SimCardQueryExportParam {
|
||||
/** 输入方式 */
|
||||
mode: QueryMode;
|
||||
/** 批量输入内容,每行 ICCID 或 ICCID MSISDN IMSI */
|
||||
batchInput?: string;
|
||||
/** 连号维度:iccid / msisdn / imsi */
|
||||
dimension?: string;
|
||||
startNum?: string;
|
||||
endNum?: string;
|
||||
/** 导出列,后端只认白名单内的字段 */
|
||||
exportColumns?: ExportColumn[];
|
||||
}
|
||||
|
||||
export interface SimCardUsageHistoryExportParam extends SimCardQueryExportParam {
|
||||
/** 所属公司部门ID,mode=dept 时必填 */
|
||||
deptId?: number;
|
||||
/** 到期日期起(含),仅 mode=dept 生效 */
|
||||
expireStartTime?: string;
|
||||
/** 到期日期止(含),仅 mode=dept 生效 */
|
||||
expireEndTime?: string;
|
||||
}
|
||||
|
||||
export interface SimCardQuerySubmitRes {
|
||||
taskId: number;
|
||||
taskNo: string;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface SimCardQueryDeptOption {
|
||||
deptId: number;
|
||||
deptName: string;
|
||||
cardCount: number;
|
||||
parentId: number;
|
||||
}
|
||||
|
||||
export interface SimCardUsageHistoryColumnsRes {
|
||||
items: ExportColumn[];
|
||||
months: string[];
|
||||
}
|
||||
|
||||
export interface SimCardUsageHistoryDeptOptionsRes {
|
||||
items: SimCardQueryDeptOption[];
|
||||
/** 当前登录用户所属部门,用于公司下拉默认值 */
|
||||
currentDeptId: number;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const get = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
get,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardRenew api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
get.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads excel renew template from backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardRenew/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits excel renew as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'renew.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardRenew/excel/submit',
|
||||
{ file },
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('prepares input renew with backend contract path', async () => {
|
||||
const { InputPrepare } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001\n8986000000000000002',
|
||||
};
|
||||
|
||||
InputPrepare(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardRenew/input/prepare', {
|
||||
...params,
|
||||
});
|
||||
});
|
||||
|
||||
it('confirms renew prepare batch with backend contract path', async () => {
|
||||
const { BatchConfirm } = await import('./index');
|
||||
const params = {
|
||||
batchNo: 'RN202607060001',
|
||||
durationMonths: 6,
|
||||
offlineContractCompleted: true,
|
||||
};
|
||||
|
||||
BatchConfirm(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardRenew/batch/confirm', {
|
||||
...params,
|
||||
});
|
||||
});
|
||||
|
||||
it('polls renew prepare result with backend contract path', async () => {
|
||||
const { PrepareResult } = await import('./index');
|
||||
const batchNo = 'RN202607060001';
|
||||
|
||||
PrepareResult(batchNo);
|
||||
|
||||
expect(get).toHaveBeenCalledWith('/iot/tSimCardRenew/prepare/result', {
|
||||
params: { batchNo },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import type {
|
||||
TSimCardRenewBatchConfirmParam,
|
||||
TSimCardRenewBatchConfirmRes,
|
||||
TSimCardRenewBatchPrepareRes,
|
||||
TSimCardRenewBatchPrepareResult,
|
||||
TSimCardRenewExcelSubmitParam,
|
||||
TSimCardRenewExcelSubmitRes,
|
||||
TSimCardRenewInputPrepareParam,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardRenew/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardRenewExcelSubmitParam,
|
||||
): Promise<TSimCardRenewExcelSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardRenew/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputPrepare(params: TSimCardRenewInputPrepareParam) {
|
||||
return requestClient.post<TSimCardRenewBatchPrepareRes>(
|
||||
'/iot/tSimCardRenew/input/prepare',
|
||||
{ ...params },
|
||||
);
|
||||
}
|
||||
|
||||
export function BatchConfirm(params: TSimCardRenewBatchConfirmParam) {
|
||||
return requestClient.post<TSimCardRenewBatchConfirmRes>(
|
||||
'/iot/tSimCardRenew/batch/confirm',
|
||||
{ ...params },
|
||||
);
|
||||
}
|
||||
|
||||
export function PrepareResult(batchNo: string) {
|
||||
return requestClient.get<TSimCardRenewBatchPrepareResult>(
|
||||
'/iot/tSimCardRenew/prepare/result',
|
||||
{ params: { batchNo } },
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
export interface TSimCardRenewInputPrepareParam {
|
||||
input: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardRenewExcelSubmitParam {
|
||||
file: File;
|
||||
}
|
||||
|
||||
export interface TSimCardRenewExcelSubmitRes {
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
resultDownloadId?: number;
|
||||
resultFileOssId?: number;
|
||||
status?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardRenewBatchPrepareRes {
|
||||
agentDefaultPriceId?: number;
|
||||
batchNo: string;
|
||||
batchType?: number;
|
||||
customerAgentId?: number;
|
||||
customerName?: string;
|
||||
failCount?: number;
|
||||
failedItems?: TSimCardRenewPrepareFailedItem[];
|
||||
failedItemsTruncated?: boolean;
|
||||
packageCode?: string;
|
||||
packageName?: string;
|
||||
billingMethod?: number;
|
||||
renewDurationUnit?: 'month' | 'year' | string;
|
||||
renewDurationUnitText?: string;
|
||||
durationValue?: number;
|
||||
durationYears?: number;
|
||||
giftDurationMonths?: number;
|
||||
priceSource?: string;
|
||||
quantity?: number;
|
||||
renewableDurationOptions?: number[];
|
||||
renewBeginDate?: string;
|
||||
renewBeginDateMax?: string;
|
||||
renewBeginDateMin?: string;
|
||||
renewUnitPrice?: number | string;
|
||||
renewablePackageCodes?: string[];
|
||||
renewablePackages?: TSimCardRenewPackageOption[];
|
||||
resultDownloadId?: number;
|
||||
resultFileOssId?: number;
|
||||
status?: string;
|
||||
targetPriceId?: number;
|
||||
total?: number;
|
||||
validCount?: number;
|
||||
isTopDept?: boolean;
|
||||
defaultPaymentMode?: 'balance' | 'offline' | string;
|
||||
availableBalance?: number | string;
|
||||
sameRenewBeginDate?: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardRenewPrepareFailedItem {
|
||||
iccid?: string;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export interface TSimCardRenewPackageOption {
|
||||
packageCode?: string;
|
||||
packageName?: string;
|
||||
renewUnitPrice?: number | string;
|
||||
renewableDurationOptions?: number[];
|
||||
}
|
||||
|
||||
export interface TSimCardRenewBatchConfirmParam {
|
||||
adminNote?: string;
|
||||
batchNo: string;
|
||||
packageCode?: string;
|
||||
buyerNote?: string;
|
||||
durationYears?: number;
|
||||
durationMonths: number;
|
||||
giftDurationMonths?: number;
|
||||
offlineContractCompleted: boolean;
|
||||
paymentMode?: 'balance' | 'offline' | string;
|
||||
packageBeginTime?: string;
|
||||
packageEndTime?: string;
|
||||
renewDate?: string;
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimCardRenewBatchConfirmRes {
|
||||
batchNo: string;
|
||||
batchType?: number;
|
||||
billingMethod?: number;
|
||||
renewDurationUnit?: 'month' | 'year' | string;
|
||||
renewDurationUnitText?: string;
|
||||
durationYears?: number;
|
||||
durationMonths?: number;
|
||||
giftDurationMonths?: number;
|
||||
orderSn?: string;
|
||||
packageCode?: string;
|
||||
packageName?: string;
|
||||
paymentMode?: string;
|
||||
payAmount?: number | string;
|
||||
payType?: number;
|
||||
availableBalance?: number | string;
|
||||
balanceDetailSerialNo?: string;
|
||||
packageBeginTime?: string;
|
||||
packageEndTime?: string;
|
||||
quantity?: number;
|
||||
renewDate?: string;
|
||||
renewUnitPrice?: number | string;
|
||||
status?: string;
|
||||
totalAmount?: number | string;
|
||||
prepareChanged?: boolean;
|
||||
priceChanged?: boolean;
|
||||
message?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type TSimCardRenewBatchAsyncStatus = number;
|
||||
|
||||
export interface TSimCardRenewBatchPrepareResult {
|
||||
batchAsyncStatus: TSimCardRenewBatchAsyncStatus;
|
||||
batchInfo?: TSimCardRenewBatchPrepareRes;
|
||||
batchNo: string;
|
||||
failReason?: string;
|
||||
runResult?: number;
|
||||
status: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardRestart api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the restart template from the backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardRestart/excel/template',
|
||||
{
|
||||
responseReturn: 'raw',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an excel restart batch as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'restart.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardRestart/excel/submit',
|
||||
{ file },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input restart batch from the backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001 14000000001 460001000000001',
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardRestart/input/submit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import type {
|
||||
TSimCardLifecycleExcelSubmitParam,
|
||||
TSimCardLifecycleInputSubmitParam,
|
||||
TSimCardLifecycleSubmitRes,
|
||||
} from '../tSimCardLifecycle/type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardRestart/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardLifecycleExcelSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardRestart/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardLifecycleInputSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardRestart/input/submit', params);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardStart api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the resume template from the backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardStart/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits an excel resume batch as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'resume.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardStart/excel/submit',
|
||||
{ file },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input resume batch from the backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001',
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardStart/input/submit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import type {
|
||||
TSimCardLifecycleExcelSubmitParam,
|
||||
TSimCardLifecycleInputSubmitParam,
|
||||
TSimCardLifecycleSubmitRes,
|
||||
} from '../tSimCardLifecycle/type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardStart/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardLifecycleExcelSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardStart/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardLifecycleInputSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardStart/input/submit', params);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardStop api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the stop template from the backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardStop/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits an excel stop batch as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'stop.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardStop/excel/submit',
|
||||
{ file },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input stop batch from the backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000001 14000000001 460001000000001',
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardStop/input/submit', params);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import type {
|
||||
TSimCardLifecycleExcelSubmitParam,
|
||||
TSimCardLifecycleInputSubmitParam,
|
||||
TSimCardLifecycleSubmitRes,
|
||||
} from '../tSimCardLifecycle/type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardStop/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardLifecycleExcelSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardStop/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardLifecycleInputSubmitParam,
|
||||
): Promise<TSimCardLifecycleSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardStop/input/submit', params);
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const get = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: { download, get, post, upload },
|
||||
}));
|
||||
|
||||
describe('tSimCardTrafficCutoff api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
get.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads the traffic cutoff template', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardTrafficCutoff/excel/template',
|
||||
{ responseReturn: 'raw' },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an excel traffic cutoff batch', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'trafficCutoff.xlsx');
|
||||
|
||||
ExcelSubmit({
|
||||
file,
|
||||
trafficCutoffCrossMonthHold: 1,
|
||||
trafficCutoffStatus: 1,
|
||||
trafficCutoffThreshold: 1024.125,
|
||||
});
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardTrafficCutoff/excel/submit',
|
||||
{
|
||||
file,
|
||||
trafficCutoffCrossMonthHold: 1,
|
||||
trafficCutoffStatus: 1,
|
||||
trafficCutoffThreshold: 1024.125,
|
||||
},
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('submits an input traffic cutoff batch', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
|
||||
InputSubmit({
|
||||
input: '8986000000000000001',
|
||||
trafficCutoffCrossMonthHold: 0,
|
||||
trafficCutoffStatus: 2,
|
||||
trafficCutoffThreshold: 2048,
|
||||
});
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardTrafficCutoff/input/submit',
|
||||
{
|
||||
input: '8986000000000000001',
|
||||
trafficCutoffCrossMonthHold: 0,
|
||||
trafficCutoffStatus: 2,
|
||||
trafficCutoffThreshold: 2048,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('queries configured cards', async () => {
|
||||
const { List } = await import('./index');
|
||||
const params = { page: 1, pageSize: 20, cardValue: '8986' };
|
||||
|
||||
List(params);
|
||||
|
||||
expect(get).toHaveBeenCalledWith('/iot/tSimCardTrafficCutoff/list', {
|
||||
params,
|
||||
});
|
||||
});
|
||||
|
||||
it('exports configured cards', async () => {
|
||||
const { Export } = await import('./index');
|
||||
const params = {
|
||||
page: 1,
|
||||
pageSize: 2000,
|
||||
deptId: 12,
|
||||
trafficCutoffStatus: 1 as const,
|
||||
};
|
||||
|
||||
Export(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardTrafficCutoff/export',
|
||||
params,
|
||||
{ responseType: 'blob' },
|
||||
);
|
||||
});
|
||||
|
||||
it('updates a traffic cutoff configuration', async () => {
|
||||
const { Edit } = await import('./index');
|
||||
const params = {
|
||||
id: 7,
|
||||
trafficCutoffCrossMonthHold: 1 as const,
|
||||
iccid: '8986000000000000001',
|
||||
trafficCutoffStatus: 1 as const,
|
||||
trafficCutoffThreshold: 1024.5,
|
||||
};
|
||||
|
||||
Edit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardTrafficCutoff/edit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
|
||||
it('clears a traffic cutoff configuration', async () => {
|
||||
const { Delete } = await import('./index');
|
||||
|
||||
Delete({ id: 7, iccid: '8986000000000000001' });
|
||||
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardTrafficCutoff/delete', {
|
||||
id: 7,
|
||||
iccid: '8986000000000000001',
|
||||
});
|
||||
});
|
||||
});
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import type {
|
||||
TSimCardTrafficCutoffDeleteParam,
|
||||
TSimCardTrafficCutoffEditParam,
|
||||
TSimCardTrafficCutoffExcelSubmitParam,
|
||||
TSimCardTrafficCutoffInputSubmitParam,
|
||||
TSimCardTrafficCutoffListParam,
|
||||
TSimCardTrafficCutoffListRes,
|
||||
TSimCardTrafficCutoffSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardTrafficCutoff/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardTrafficCutoffExcelSubmitParam,
|
||||
): Promise<TSimCardTrafficCutoffSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardTrafficCutoff/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
trafficCutoffStatus: params.trafficCutoffStatus,
|
||||
trafficCutoffThreshold: params.trafficCutoffThreshold,
|
||||
trafficCutoffCrossMonthHold: params.trafficCutoffCrossMonthHold,
|
||||
},
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardTrafficCutoffInputSubmitParam,
|
||||
): Promise<TSimCardTrafficCutoffSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardTrafficCutoff/input/submit', {
|
||||
input: params.input,
|
||||
trafficCutoffStatus: params.trafficCutoffStatus,
|
||||
trafficCutoffThreshold: params.trafficCutoffThreshold,
|
||||
trafficCutoffCrossMonthHold: params.trafficCutoffCrossMonthHold,
|
||||
});
|
||||
}
|
||||
|
||||
export function List(params: TSimCardTrafficCutoffListParam) {
|
||||
return requestClient.get<TSimCardTrafficCutoffListRes>(
|
||||
'/iot/tSimCardTrafficCutoff/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
export function Export(params: TSimCardTrafficCutoffListParam) {
|
||||
return requestClient.post<Blob>('/iot/tSimCardTrafficCutoff/export', params, {
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function Edit(params: TSimCardTrafficCutoffEditParam) {
|
||||
return requestClient.post<unknown>('/iot/tSimCardTrafficCutoff/edit', params);
|
||||
}
|
||||
|
||||
export function Delete(params: TSimCardTrafficCutoffDeleteParam) {
|
||||
return requestClient.post<unknown>(
|
||||
'/iot/tSimCardTrafficCutoff/delete',
|
||||
params,
|
||||
);
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import type { GlobalListRes } from '#/types/global';
|
||||
|
||||
export interface TSimCardTrafficCutoffExcelSubmitParam {
|
||||
trafficCutoffCrossMonthHold: 0 | 1;
|
||||
file: File;
|
||||
trafficCutoffStatus: 0 | 1 | 2;
|
||||
trafficCutoffThreshold: number;
|
||||
}
|
||||
|
||||
export interface TSimCardTrafficCutoffInputSubmitParam {
|
||||
trafficCutoffCrossMonthHold: 0 | 1;
|
||||
input: string;
|
||||
trafficCutoffStatus: 0 | 1 | 2;
|
||||
trafficCutoffThreshold: number;
|
||||
}
|
||||
|
||||
export interface TSimCardTrafficCutoffSubmitRes {
|
||||
batchNo: string;
|
||||
batchType: number;
|
||||
batchAsyncStatus: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface TSimCardTrafficCutoffModel {
|
||||
trafficCutoffCrossMonthHold: 0 | 1;
|
||||
id: number;
|
||||
iccid: string;
|
||||
msisdn: string;
|
||||
imsi: string;
|
||||
imei: string;
|
||||
chanName?: string;
|
||||
deptName?: string;
|
||||
packageName?: string;
|
||||
bossCardStatus?: number;
|
||||
trafficCutoffStatus: 1 | 2;
|
||||
trafficCutoffThreshold: number;
|
||||
}
|
||||
|
||||
export interface TSimCardTrafficCutoffListParam {
|
||||
includeUnconfigured?: boolean;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
cardValue?: string;
|
||||
imei?: string;
|
||||
deptId?: number | string;
|
||||
trafficCutoffStatus?: 1 | 2;
|
||||
}
|
||||
|
||||
export type TSimCardTrafficCutoffListRes =
|
||||
GlobalListRes<TSimCardTrafficCutoffModel>;
|
||||
|
||||
export interface TSimCardTrafficCutoffEditParam {
|
||||
trafficCutoffCrossMonthHold: 0 | 1;
|
||||
id: number;
|
||||
iccid: string;
|
||||
trafficCutoffStatus: 1 | 2;
|
||||
trafficCutoffThreshold: number;
|
||||
}
|
||||
|
||||
export interface TSimCardTrafficCutoffDeleteParam {
|
||||
id: number;
|
||||
iccid: string;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import type { TSimCardUnsubSubmitRes } from './type';
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const download = vi.fn();
|
||||
const post = vi.fn();
|
||||
const upload = vi.fn();
|
||||
|
||||
vi.mock('#/api/request', () => ({
|
||||
requestClient: {
|
||||
download,
|
||||
post,
|
||||
upload,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('tSimCardUnsub api', () => {
|
||||
beforeEach(() => {
|
||||
download.mockReset();
|
||||
post.mockReset();
|
||||
upload.mockReset();
|
||||
});
|
||||
|
||||
it('downloads excel unsubscribe template from backend contract path', async () => {
|
||||
const { DownloadTemplate } = await import('./index');
|
||||
|
||||
DownloadTemplate();
|
||||
|
||||
expect(download).toHaveBeenCalledWith('/iot/tSimCardUnsub/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
});
|
||||
|
||||
it('submits excel unsubscribe as file-only form data', async () => {
|
||||
const { ExcelSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'unsubscribe.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardUnsub/excel/submit',
|
||||
{ file },
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('submits input unsubscribe from backend contract path', async () => {
|
||||
const { InputSubmit } = await import('./index');
|
||||
const params = {
|
||||
input: '8986000000000000000',
|
||||
remark: 'unsubscribe remark',
|
||||
};
|
||||
|
||||
InputSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardUnsub/input/submit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
|
||||
it('submits range unsubscribe from backend contract path', async () => {
|
||||
const { RangeSubmit } = await import('./index');
|
||||
const params = {
|
||||
endIccid: '8986000000000000009',
|
||||
endImsi: '460000000000009',
|
||||
endMsisdn: '13000000009',
|
||||
remark: 'unsubscribe remark',
|
||||
startIccid: '8986000000000000001',
|
||||
startImsi: '460000000000001',
|
||||
startMsisdn: '13000000001',
|
||||
};
|
||||
|
||||
RangeSubmit(params);
|
||||
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardUnsub/range/submit',
|
||||
params,
|
||||
);
|
||||
});
|
||||
|
||||
it('exposes batchAsyncStatus on the submit response type so async Pending is representable', async () => {
|
||||
const res: TSimCardUnsubSubmitRes = {
|
||||
batchAsyncStatus: 0,
|
||||
batchNo: 'B202607210001',
|
||||
batchType: 1,
|
||||
};
|
||||
|
||||
expect(res.batchAsyncStatus).toBe(0);
|
||||
expect(res.batchNo).toBe('B202607210001');
|
||||
});
|
||||
|
||||
it('keeps excel/input/range submit endpoints pointing at the backend contract paths', async () => {
|
||||
const { ExcelSubmit, InputSubmit, RangeSubmit } = await import('./index');
|
||||
const file = new File(['iccid'], 'unsubscribe.xlsx');
|
||||
|
||||
ExcelSubmit({ file });
|
||||
InputSubmit({ input: '8986000000000000000' });
|
||||
RangeSubmit({
|
||||
endIccid: '8986000000000000009',
|
||||
endImsi: '460000000000009',
|
||||
endMsisdn: '13000000009',
|
||||
startIccid: '8986000000000000001',
|
||||
startImsi: '460000000000001',
|
||||
startMsisdn: '13000000001',
|
||||
});
|
||||
|
||||
expect(upload).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardUnsub/excel/submit',
|
||||
{ file },
|
||||
{ timeout: 60_000 },
|
||||
);
|
||||
expect(post).toHaveBeenCalledWith('/iot/tSimCardUnsub/input/submit', {
|
||||
input: '8986000000000000000',
|
||||
});
|
||||
expect(post).toHaveBeenCalledWith(
|
||||
'/iot/tSimCardUnsub/range/submit',
|
||||
expect.objectContaining({
|
||||
startIccid: '8986000000000000001',
|
||||
endIccid: '8986000000000000009',
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import type {
|
||||
TSimCardUnsubExcelSubmitParam,
|
||||
TSimCardUnsubInputSubmitParam,
|
||||
TSimCardUnsubRangeSubmitParam,
|
||||
TSimCardUnsubSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate() {
|
||||
return requestClient.download('/iot/tSimCardUnsub/excel/template', {
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimCardUnsubExcelSubmitParam,
|
||||
): Promise<TSimCardUnsubSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimCardUnsub/excel/submit',
|
||||
{ file: params.file },
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimCardUnsubInputSubmitParam,
|
||||
): Promise<TSimCardUnsubSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardUnsub/input/submit', params);
|
||||
}
|
||||
|
||||
export function RangeSubmit(
|
||||
params: TSimCardUnsubRangeSubmitParam,
|
||||
): Promise<TSimCardUnsubSubmitRes> {
|
||||
return requestClient.post('/iot/tSimCardUnsub/range/submit', params);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/** 提交Excel卡退订请求参数 */
|
||||
export interface TSimCardUnsubExcelSubmitParam {
|
||||
/** Excel文件 */
|
||||
file: File;
|
||||
}
|
||||
|
||||
/** 提交批量输入卡退订请求参数 */
|
||||
export interface TSimCardUnsubInputSubmitParam {
|
||||
/** 批量输入ICCID文本 */
|
||||
input: string;
|
||||
/** 退订备注 */
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
/** 提交连号卡退订请求参数 */
|
||||
export interface TSimCardUnsubRangeSubmitParam {
|
||||
/** 结束ICCID */
|
||||
endIccid: string;
|
||||
/** 结束IMSI */
|
||||
endImsi: string;
|
||||
/** 结束MSISDN */
|
||||
endMsisdn: string;
|
||||
/** 退订备注 */
|
||||
remark?: string;
|
||||
/** 起始ICCID */
|
||||
startIccid: string;
|
||||
/** 起始IMSI */
|
||||
startImsi: string;
|
||||
/** 起始MSISDN */
|
||||
startMsisdn: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
/** 卡退订提交响应 */
|
||||
export interface TSimCardUnsubSubmitRes {
|
||||
/** 批次异步处理状态(Pending 等) */
|
||||
batchAsyncStatus?: number;
|
||||
/** 批次号 */
|
||||
batchNo?: string;
|
||||
/** 批次类型 */
|
||||
batchType?: number;
|
||||
/** 失败行数 */
|
||||
failCount?: number;
|
||||
/** 实际退订数量 */
|
||||
quantity?: number;
|
||||
/** 结果下载任务ID */
|
||||
resultDownloadId?: number;
|
||||
/** 结果文件OSS ID */
|
||||
resultFileOssId?: number;
|
||||
/** 导入状态 */
|
||||
status?: string;
|
||||
/** 解析总行数 */
|
||||
total?: number;
|
||||
/** 校验通过行数 */
|
||||
validCount?: number;
|
||||
[property: string]: any;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import type {
|
||||
TSimPoolAddPackageBatchConfirmParam,
|
||||
TSimPoolAddPackageBatchConfirmRes,
|
||||
TSimPoolAddPackageOptionsRes,
|
||||
TSimPoolAddPackagePrepareResult,
|
||||
TSimPoolBindPackageAddPackageExcelSubmitParam,
|
||||
TSimPoolBindPackageAddPackageInputPrepareParam,
|
||||
TSimPoolBindPackageAddPackageInputPrepareRes,
|
||||
TSimPoolBindPackageAddPackageInputSubmitParam,
|
||||
TSimPoolBindPackageAddPackageSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadAddPackageTemplate() {
|
||||
return requestClient.download(
|
||||
'/iot/tSimPoolBindPackage/addPackage/excel/template',
|
||||
{
|
||||
responseReturn: 'raw',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageExcelSubmit(
|
||||
params: TSimPoolBindPackageAddPackageExcelSubmitParam,
|
||||
): Promise<TSimPoolBindPackageAddPackageSubmitRes> {
|
||||
return requestClient.upload(
|
||||
'/iot/tSimPoolBindPackage/addPackage/excel/submit',
|
||||
{
|
||||
file: params.file,
|
||||
manualConfirm: params.manualConfirm,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageOptions(params: {
|
||||
flowPoolCodes: string[];
|
||||
}): Promise<TSimPoolAddPackageOptionsRes> {
|
||||
return requestClient.post(
|
||||
'/iot/tSimPoolBindPackage/addPackage/options',
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackagePaymentContext(): Promise<TSimPoolAddPackageOptionsRes> {
|
||||
return requestClient.post(
|
||||
'/iot/tSimPoolBindPackage/addPackage/payment-context',
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageInputSubmit(
|
||||
params: TSimPoolBindPackageAddPackageInputSubmitParam,
|
||||
): Promise<TSimPoolBindPackageAddPackageSubmitRes> {
|
||||
return requestClient.post(
|
||||
'/iot/tSimPoolBindPackage/addPackage/input/submit',
|
||||
{
|
||||
...params,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageInputPrepare(
|
||||
params: TSimPoolBindPackageAddPackageInputPrepareParam,
|
||||
): Promise<TSimPoolBindPackageAddPackageInputPrepareRes> {
|
||||
return requestClient.post(
|
||||
'/iot/tSimPoolBindPackage/addPackage/input/prepare',
|
||||
{
|
||||
...params,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackagePrepareResult(
|
||||
batchNo: string,
|
||||
): Promise<TSimPoolAddPackagePrepareResult> {
|
||||
return requestClient.get(
|
||||
'/iot/tSimPoolBindPackage/addPackage/prepare/result',
|
||||
{
|
||||
params: { batchNo },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function AddPackageBatchConfirm(
|
||||
params: TSimPoolAddPackageBatchConfirmParam,
|
||||
): Promise<TSimPoolAddPackageBatchConfirmRes> {
|
||||
return requestClient.post(
|
||||
'/iot/tSimPoolBindPackage/addPackage/batch/confirm',
|
||||
{
|
||||
...params,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
export type AddPackageEffectiveMode = 'current_month';
|
||||
export type AddPackagePaymentMode = 'balance' | 'offline';
|
||||
|
||||
export interface TSimPoolBindPackageAddPackageExcelSubmitParam {
|
||||
file: File;
|
||||
paymentMode?: AddPackagePaymentMode;
|
||||
offlineContractCompleted?: boolean;
|
||||
manualConfirm?: boolean;
|
||||
}
|
||||
|
||||
export interface TSimPoolBindPackageAddPackageInputSubmitParam {
|
||||
input: string;
|
||||
packageCode?: string;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
remark?: string;
|
||||
paymentMode?: AddPackagePaymentMode;
|
||||
offlineContractCompleted?: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimPoolBindPackageAddPackageInputPrepareParam {
|
||||
input: string;
|
||||
packageCode?: string;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimPoolBindPackageAddPackageSubmitRes {
|
||||
batchAsyncStatus?: number;
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
targetBatchType?: number;
|
||||
total?: number;
|
||||
validCount?: number;
|
||||
failCount?: number;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type TSimPoolBindPackageAddPackageInputPrepareRes =
|
||||
TSimPoolAddPackagePrepareResult;
|
||||
|
||||
export interface TSimPoolAddPackageBatchConfirmParam {
|
||||
batchNo: string;
|
||||
packageCode?: string;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
remark?: string;
|
||||
paymentMode?: AddPackagePaymentMode | string;
|
||||
offlineContractCompleted?: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimPoolAddPackageBatchConfirmRes {
|
||||
batchAsyncStatus?: number;
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
packageCode?: string;
|
||||
status?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface TSimPoolAddPackagePaymentAccount {
|
||||
payerDeptId: number;
|
||||
targetCount: number;
|
||||
requiredAmount: number | string;
|
||||
availableBalance: number | string;
|
||||
balanceEnough: boolean;
|
||||
}
|
||||
|
||||
export interface TSimPoolAddPackageOption {
|
||||
flowMb: number;
|
||||
packageCode: string;
|
||||
packageName: string;
|
||||
unitPrice?: number | string;
|
||||
totalAmount?: number | string;
|
||||
priceAvailable?: boolean;
|
||||
priceReason?: string;
|
||||
paymentAccounts?: TSimPoolAddPackagePaymentAccount[];
|
||||
}
|
||||
|
||||
export interface TSimPoolAddPackageOptionsRes {
|
||||
items: TSimPoolAddPackageOption[];
|
||||
isTopDept?: boolean;
|
||||
defaultPaymentMode?: AddPackagePaymentMode | string;
|
||||
availableBalance?: number | string;
|
||||
}
|
||||
|
||||
export interface TSimPoolAddPackagePrepareResult {
|
||||
availableBalance?: number | string;
|
||||
batchAsyncStatus?: number;
|
||||
batchInfo?: Record<string, any>;
|
||||
batchNo?: string;
|
||||
batchType?: number;
|
||||
effectiveMode?: AddPackageEffectiveMode | string;
|
||||
effectiveModeText?: string;
|
||||
effectiveTime?: string;
|
||||
expectedExpireTime?: string;
|
||||
failCount?: number;
|
||||
failReason?: string;
|
||||
flowMb?: number | string;
|
||||
isTopDept?: boolean;
|
||||
packageCode?: string;
|
||||
packageName?: string;
|
||||
paymentAccounts?: TSimPoolAddPackagePaymentAccount[];
|
||||
availablePackages?: TSimPoolAddPackageOption[];
|
||||
quantity?: number;
|
||||
runResult?: number;
|
||||
snapshot?: Record<string, any>;
|
||||
status?: string;
|
||||
successCount?: number;
|
||||
targetBatchType?: number;
|
||||
total?: number;
|
||||
totalAmount?: number | string;
|
||||
unitPrice?: number | string;
|
||||
validCount?: number;
|
||||
defaultPaymentMode?: AddPackagePaymentMode | string;
|
||||
[property: string]: any;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import type {
|
||||
TSimWarningConfigEmailCodeParam,
|
||||
TSimWarningConfigExcelSubmitParam,
|
||||
TSimWarningConfigInputSubmitParam,
|
||||
TSimWarningConfigRangeSubmitParam,
|
||||
TSimWarningConfigSubmitRes,
|
||||
} from './type';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export function DownloadTemplate(params?: { itemType?: number }) {
|
||||
return requestClient.download('/iot/tSimWarningConfig/excel/template', {
|
||||
params,
|
||||
responseReturn: 'raw',
|
||||
});
|
||||
}
|
||||
|
||||
export function SendEmailCode(params: TSimWarningConfigEmailCodeParam) {
|
||||
return requestClient.post('/iot/tSimWarningConfig/email/code', params);
|
||||
}
|
||||
|
||||
export function ExcelSubmit(
|
||||
params: TSimWarningConfigExcelSubmitParam,
|
||||
): Promise<TSimWarningConfigSubmitRes> {
|
||||
const { file, ...data } = params;
|
||||
return requestClient.upload(
|
||||
'/iot/tSimWarningConfig/excel/submit',
|
||||
{
|
||||
file,
|
||||
...data,
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function InputSubmit(
|
||||
params: TSimWarningConfigInputSubmitParam,
|
||||
): Promise<TSimWarningConfigSubmitRes> {
|
||||
return requestClient.post('/iot/tSimWarningConfig/input/submit', params);
|
||||
}
|
||||
|
||||
export function RangeSubmit(
|
||||
params: TSimWarningConfigRangeSubmitParam,
|
||||
): Promise<TSimWarningConfigSubmitRes> {
|
||||
return requestClient.post('/iot/tSimWarningConfig/range/submit', params);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user