Compare commits
No commits in common. "master" and "v2026.01" have entirely different histories.
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"singleQuote": true
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
---
|
|
||||||
'@vben/styles': patch
|
|
||||||
'@vben-core/form-ui': patch
|
|
||||||
'@vben/web-naive': patch
|
|
||||||
---
|
|
||||||
|
|
||||||
feat(@core/form-ui): 新增 useVbenForm 数组编辑器 VbenFormFieldArray
|
|
||||||
|
Before Width: | Height: | Size: 169 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
|
@ -6,10 +6,10 @@ runs:
|
||||||
using: 'composite'
|
using: 'composite'
|
||||||
steps:
|
steps:
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@v6
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ jobs:
|
||||||
- windows-latest
|
- windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ jobs:
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@v6
|
uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
run_install: false
|
run_install: false
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ jobs:
|
||||||
- windows-latest
|
- windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,11 +57,11 @@ jobs:
|
||||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v4
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
build-mode: ${{ matrix.build-mode }}
|
build-mode: ${{ matrix.build-mode }}
|
||||||
|
|
@ -89,6 +89,6 @@ jobs:
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v4
|
uses: github/codeql-action/analyze@v3
|
||||||
with:
|
with:
|
||||||
category: '/language:${{matrix.language}}'
|
category: '/language:${{matrix.language}}'
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ jobs:
|
||||||
run: pnpm build:play
|
run: pnpm build:play
|
||||||
|
|
||||||
- name: Sync Playground files
|
- name: Sync Playground files
|
||||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||||
with:
|
with:
|
||||||
server: ${{ secrets.PRO_FTP_HOST }}
|
server: ${{ secrets.PRO_FTP_HOST }}
|
||||||
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }}
|
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }}
|
||||||
|
|
@ -43,7 +43,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ jobs:
|
||||||
run: pnpm build:docs
|
run: pnpm build:docs
|
||||||
|
|
||||||
- name: Sync Docs files
|
- name: Sync Docs files
|
||||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||||
with:
|
with:
|
||||||
server: ${{ secrets.PRO_FTP_HOST }}
|
server: ${{ secrets.PRO_FTP_HOST }}
|
||||||
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
|
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
|
||||||
|
|
@ -67,7 +67,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ jobs:
|
||||||
run: pnpm run build:antd
|
run: pnpm run build:antd
|
||||||
|
|
||||||
- name: Sync files
|
- name: Sync files
|
||||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||||
with:
|
with:
|
||||||
server: ${{ secrets.PRO_FTP_HOST }}
|
server: ${{ secrets.PRO_FTP_HOST }}
|
||||||
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
|
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
|
||||||
|
|
@ -98,7 +98,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ jobs:
|
||||||
run: pnpm run build:ele
|
run: pnpm run build:ele
|
||||||
|
|
||||||
- name: Sync files
|
- name: Sync files
|
||||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||||
with:
|
with:
|
||||||
server: ${{ secrets.PRO_FTP_HOST }}
|
server: ${{ secrets.PRO_FTP_HOST }}
|
||||||
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
|
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
|
||||||
|
|
@ -129,7 +129,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ jobs:
|
||||||
run: pnpm run build:naive
|
run: pnpm run build:naive
|
||||||
|
|
||||||
- name: Sync files
|
- name: Sync files
|
||||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||||
with:
|
with:
|
||||||
server: ${{ secrets.PRO_FTP_HOST }}
|
server: ${{ secrets.PRO_FTP_HOST }}
|
||||||
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }}
|
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,6 @@ jobs:
|
||||||
if: github.repository == 'vbenjs/vue-vben-admin'
|
if: github.repository == 'vbenjs/vue-vben-admin'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: release-drafter/release-drafter@v7
|
- uses: release-drafter/release-drafter@v6
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# 关闭未活动的 Issues
|
# 关闭未活动的 Issues
|
||||||
- name: Close Inactive Issues
|
- name: Close Inactive Issues
|
||||||
uses: actions/stale@v10
|
uses: actions/stale@v9
|
||||||
with:
|
with:
|
||||||
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
|
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
|
||||||
stale-issue-label: needs-reproduction # Label that flags an issue as stale.
|
stale-issue-label: needs-reproduction # Label that flags an issue as stale.
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: remove enhancement pending
|
- name: remove enhancement pending
|
||||||
if: github.event.label.name == 'enhancement'
|
if: github.event.label.name == 'enhancement'
|
||||||
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
|
uses: actions-cool/issues-helper@v3
|
||||||
with:
|
with:
|
||||||
actions: 'remove-labels'
|
actions: 'remove-labels'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
@ -27,7 +27,7 @@ jobs:
|
||||||
|
|
||||||
- name: remove bug pending
|
- name: remove bug pending
|
||||||
if: github.event.label.name == 'bug'
|
if: github.event.label.name == 'bug'
|
||||||
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
|
uses: actions-cool/issues-helper@v3
|
||||||
with:
|
with:
|
||||||
actions: 'remove-labels'
|
actions: 'remove-labels'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
@ -36,7 +36,7 @@ jobs:
|
||||||
|
|
||||||
- name: needs reproduction
|
- name: needs reproduction
|
||||||
if: github.event.label.name == 'needs reproduction'
|
if: github.event.label.name == 'needs reproduction'
|
||||||
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
|
uses: actions-cool/issues-helper@v3
|
||||||
with:
|
with:
|
||||||
actions: 'create-comment, remove-labels'
|
actions: 'create-comment, remove-labels'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
if: github.repository == 'vbenjs/vue-vben-admin'
|
if: github.repository == 'vbenjs/vue-vben-admin'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v6
|
- uses: dessant/lock-threads@v5
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
issue-inactive-days: '14'
|
issue-inactive-days: '14'
|
||||||
|
|
|
||||||
|
|
@ -3,48 +3,78 @@ name: Create Release Tag
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v*.*.*'
|
- 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
env:
|
||||||
tag:
|
HUSKY: '0'
|
||||||
description: 'Tag to create (e.g. v1.2.3)'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
build:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
if: github.repository == 'vbenjs/vue-vben-admin'
|
if: github.repository == 'vbenjs/vue-vben-admin'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [20]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Extract version
|
# - name: Checkout code
|
||||||
|
# uses: actions/checkout@v4
|
||||||
|
# with:
|
||||||
|
# fetch-depth: 0
|
||||||
|
|
||||||
|
# - name: Install pnpm
|
||||||
|
# uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
|
# - name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
# uses: actions/setup-node@v4
|
||||||
|
# with:
|
||||||
|
# node-version: ${{ matrix.node-version }}
|
||||||
|
# cache: "pnpm"
|
||||||
|
|
||||||
|
# - name: Install dependencies
|
||||||
|
# run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# - name: Test and Build
|
||||||
|
# run: |
|
||||||
|
# pnpm run test
|
||||||
|
# pnpm run build
|
||||||
|
|
||||||
|
- name: version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
tag=${GITHUB_REF/refs\/tags\//}
|
||||||
raw_tag="${{ inputs.tag }}"
|
version=${tag#v}
|
||||||
else
|
major=${version%%.*}
|
||||||
raw_tag="${GITHUB_REF_NAME}"
|
echo "tag=${tag}" >> $GITHUB_OUTPUT
|
||||||
fi
|
echo "version=${version}" >> $GITHUB_OUTPUT
|
||||||
# Normalize: ensure v prefix
|
echo "major=${major}" >> $GITHUB_OUTPUT
|
||||||
tag="${raw_tag}"
|
|
||||||
[[ "${tag:0:1}" != "v" ]] && tag="v${tag}"
|
|
||||||
version="${tag#v}"
|
|
||||||
major="${version%%.*}"
|
|
||||||
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
|
|
||||||
echo "version=${version}" >> "${GITHUB_OUTPUT}"
|
|
||||||
echo "major=${major}" >> "${GITHUB_OUTPUT}"
|
|
||||||
|
|
||||||
- uses: release-drafter/release-drafter@v7
|
- uses: release-drafter/release-drafter@v6
|
||||||
with:
|
with:
|
||||||
version: ${{ steps.version.outputs.version }}
|
version: ${{ steps.version.outputs.version }}
|
||||||
publish: true
|
publish: true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# - name: force update major tag
|
||||||
|
# run: |
|
||||||
|
# git tag v${{ steps.version.outputs.major }} ${{ steps.version.outputs.tag }} -f
|
||||||
|
# git push origin refs/tags/v${{ steps.version.outputs.major }} -f
|
||||||
|
|
||||||
|
# - name: Create Release for Tag
|
||||||
|
# id: release_tag
|
||||||
|
# uses: ncipollo/release-action@v1
|
||||||
|
# with:
|
||||||
|
# token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# generateReleaseNotes: "true"
|
||||||
|
# body: |
|
||||||
|
# > Please refer to [CHANGELOG.md](https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md) for details.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Validate PR title
|
- name: Validate PR title
|
||||||
uses: amannn/action-semantic-pull-request@v6
|
uses: amannn/action-semantic-pull-request@v5
|
||||||
with:
|
with:
|
||||||
wip: true
|
wip: true
|
||||||
subjectPattern: ^(?![A-Z]).+$
|
subjectPattern: ^(?![A-Z]).+$
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ jobs:
|
||||||
if: github.repository == 'vbenjs/vue-vben-admin'
|
if: github.repository == 'vbenjs/vue-vben-admin'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v10
|
- uses: actions/stale@v9
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
|
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ yarn.lock
|
||||||
package-lock.json
|
package-lock.json
|
||||||
.VSCodeCounter
|
.VSCodeCounter
|
||||||
**/backend-mock/data
|
**/backend-mock/data
|
||||||
.omx
|
|
||||||
.pnpm-store
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
@ -51,15 +50,3 @@ vite.config.ts.*
|
||||||
*.sw?
|
*.sw?
|
||||||
.history
|
.history
|
||||||
.cursor
|
.cursor
|
||||||
|
|
||||||
# AI
|
|
||||||
.agent
|
|
||||||
.agents
|
|
||||||
.claude
|
|
||||||
.codex
|
|
||||||
skills-lock.json
|
|
||||||
.atomcode
|
|
||||||
datalog
|
|
||||||
|
|
||||||
# Playwright CLI 录制产物(本地调试,不入库)
|
|
||||||
.playwright-cli
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
24.16.0
|
22.1.0
|
||||||
|
|
|
||||||
12
.npmrc
|
|
@ -1 +1,13 @@
|
||||||
registry=https://registry.npmmirror.com
|
registry=https://registry.npmmirror.com
|
||||||
|
public-hoist-pattern[]=lefthook
|
||||||
|
public-hoist-pattern[]=eslint
|
||||||
|
public-hoist-pattern[]=prettier
|
||||||
|
public-hoist-pattern[]=prettier-plugin-tailwindcss
|
||||||
|
public-hoist-pattern[]=stylelint
|
||||||
|
public-hoist-pattern[]=*postcss*
|
||||||
|
public-hoist-pattern[]=@commitlint/*
|
||||||
|
public-hoist-pattern[]=czg
|
||||||
|
|
||||||
|
strict-peer-dependencies=false
|
||||||
|
auto-install-peers=true
|
||||||
|
dedupe-peer-dependents=true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
dist
|
||||||
|
dev-dist
|
||||||
|
.local
|
||||||
|
.output.js
|
||||||
|
node_modules
|
||||||
|
.nvmrc
|
||||||
|
coverage
|
||||||
|
CODEOWNERS
|
||||||
|
.nitro
|
||||||
|
.output
|
||||||
|
|
||||||
|
|
||||||
|
**/*.svg
|
||||||
|
**/*.sh
|
||||||
|
|
||||||
|
public
|
||||||
|
.npmrc
|
||||||
|
*-lock.yaml
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from '@vben/prettier-config';
|
||||||
|
|
@ -2,7 +2,3 @@ dist
|
||||||
public
|
public
|
||||||
__tests__
|
__tests__
|
||||||
coverage
|
coverage
|
||||||
.codex
|
|
||||||
.claude
|
|
||||||
.agent
|
|
||||||
.agents
|
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,14 @@
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
// Vue 3 的语言支持
|
// Vue 3 的语言支持
|
||||||
"Vue.volar",
|
"Vue.volar",
|
||||||
// 将 eslint 集成到 VS Code 中。
|
// 将 ESLint JavaScript 集成到 VS Code 中。
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
// 将 oxlint 集成到 VS Code 中。
|
|
||||||
"oxc.oxc-vscode",
|
|
||||||
// Visual Studio Code 的官方 Stylelint 扩展
|
// Visual Studio Code 的官方 Stylelint 扩展
|
||||||
"stylelint.vscode-stylelint",
|
"stylelint.vscode-stylelint",
|
||||||
// 使用 oxfmt 的代码格式化程序
|
// 使用 Prettier 的代码格式化程序
|
||||||
"oxc.oxc-vscode",
|
"esbenp.prettier-vscode",
|
||||||
// 支持 dotenv 文件语法
|
// 支持 dotenv 文件语法
|
||||||
"mikestead.dotenv",
|
"mikestead.dotenv",
|
||||||
// YAML 语言支持,供 ESLint 校验 pnpm-workspace.yaml 等文件
|
|
||||||
"redhat.vscode-yaml",
|
|
||||||
// 源代码的拼写检查器
|
// 源代码的拼写检查器
|
||||||
"streetsidesoftware.code-spell-checker",
|
"streetsidesoftware.code-spell-checker",
|
||||||
// Tailwind CSS 的官方 VS Code 插件
|
// Tailwind CSS 的官方 VS Code 插件
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,6 @@
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
|
||||||
"type": "chrome",
|
|
||||||
"name": "vben admin antd dev",
|
|
||||||
"request": "launch",
|
|
||||||
"url": "http://localhost:5999",
|
|
||||||
"env": { "NODE_ENV": "development" },
|
|
||||||
"sourceMaps": true,
|
|
||||||
"webRoot": "${workspaceFolder}/apps/web-antdv-next"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
"name": "vben admin antd dev",
|
"name": "vben admin antd dev",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/theme.css",
|
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts",
|
||||||
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
|
|
||||||
// workbench
|
// workbench
|
||||||
"workbench.list.smoothScrolling": true,
|
"workbench.list.smoothScrolling": true,
|
||||||
"workbench.startupEditor": "newUntitledFile",
|
"workbench.startupEditor": "newUntitledFile",
|
||||||
|
|
@ -32,51 +31,39 @@
|
||||||
"editor.autoClosingOvertype": "always",
|
"editor.autoClosingOvertype": "always",
|
||||||
"editor.autoClosingQuotes": "beforeWhitespace",
|
"editor.autoClosingQuotes": "beforeWhitespace",
|
||||||
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
|
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
|
||||||
"editor.quickSuggestions": {
|
|
||||||
"strings": "on"
|
|
||||||
},
|
|
||||||
|
|
||||||
// lint && format
|
|
||||||
"oxc.enable": true,
|
|
||||||
"oxc.typeAware": false,
|
|
||||||
"oxc.configPath": "oxlint.config.ts",
|
|
||||||
"oxc.fmt.configPath": "oxfmt.config.ts",
|
|
||||||
"eslint.useFlatConfig": true,
|
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit",
|
"source.fixAll.eslint": "explicit",
|
||||||
"source.fixAll.oxc": "explicit",
|
|
||||||
"source.fixAll.stylelint": "explicit",
|
"source.fixAll.stylelint": "explicit",
|
||||||
"source.organizeImports": "never"
|
"source.organizeImports": "never"
|
||||||
},
|
},
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"[html]": {
|
"[html]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[css]": {
|
"[css]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[scss]": {
|
"[scss]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[javascript]": {
|
"[javascript]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[json]": {
|
"[json]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[markdown]": {
|
"[markdown]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[jsonc]": {
|
"[jsonc]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[vue]": {
|
"[vue]": {
|
||||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
|
|
||||||
// extensions
|
// extensions
|
||||||
"extensions.ignoreRecommendations": true,
|
"extensions.ignoreRecommendations": true,
|
||||||
|
|
||||||
|
|
@ -92,7 +79,6 @@
|
||||||
"files.insertFinalNewline": true,
|
"files.insertFinalNewline": true,
|
||||||
"files.simpleDialog.enable": true,
|
"files.simpleDialog.enable": true,
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"*.css": "tailwindcss",
|
|
||||||
"*.ejs": "html",
|
"*.ejs": "html",
|
||||||
"*.art": "html",
|
"*.art": "html",
|
||||||
"**/tsconfig.json": "jsonc",
|
"**/tsconfig.json": "jsonc",
|
||||||
|
|
@ -132,7 +118,7 @@
|
||||||
// search
|
// search
|
||||||
"search.searchEditor.singleClickBehaviour": "peekDefinition",
|
"search.searchEditor.singleClickBehaviour": "peekDefinition",
|
||||||
"search.followSymlinks": false,
|
"search.followSymlinks": false,
|
||||||
// 使用搜索功能时,将这些文件和文件夹排除在外
|
// 在使用搜索功能时,将这些文件夹/文件排除在外
|
||||||
"search.exclude": {
|
"search.exclude": {
|
||||||
"**/node_modules": true,
|
"**/node_modules": true,
|
||||||
"**/*.log": true,
|
"**/*.log": true,
|
||||||
|
|
@ -173,7 +159,7 @@
|
||||||
"emmet.triggerExpansionOnTab": false,
|
"emmet.triggerExpansionOnTab": false,
|
||||||
|
|
||||||
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
|
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
|
||||||
"errorLens.excludeBySource": ["cSpell", "Grammarly"],
|
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"],
|
||||||
|
|
||||||
"stylelint.enable": true,
|
"stylelint.enable": true,
|
||||||
"stylelint.packageManager": "pnpm",
|
"stylelint.packageManager": "pnpm",
|
||||||
|
|
@ -181,10 +167,9 @@
|
||||||
"stylelint.customSyntax": "postcss-html",
|
"stylelint.customSyntax": "postcss-html",
|
||||||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
||||||
|
|
||||||
"js/ts.tsdk.path": "node_modules/typescript/lib",
|
"typescript.inlayHints.enumMemberValues.enabled": true,
|
||||||
"js/ts.inlayHints.enumMemberValues.enabled": true,
|
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||||
"js/ts.preferences.preferTypeOnlyAutoImports": true,
|
"typescript.preferences.includePackageJsonAutoImports": "on",
|
||||||
"js/ts.preferences.includePackageJsonAutoImports": "on",
|
|
||||||
|
|
||||||
"eslint.validate": [
|
"eslint.validate": [
|
||||||
"javascript",
|
"javascript",
|
||||||
|
|
@ -208,7 +193,7 @@
|
||||||
"*": false
|
"*": false
|
||||||
},
|
},
|
||||||
|
|
||||||
"cssVariables.lookupFiles": ["packages/@core/base/design/src/**/*.css"],
|
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"],
|
||||||
|
|
||||||
"i18n-ally.localesPaths": [
|
"i18n-ally.localesPaths": [
|
||||||
"packages/locales/src/langs",
|
"packages/locales/src/langs",
|
||||||
|
|
@ -233,9 +218,12 @@
|
||||||
"*.env": "$(capture).env.*",
|
"*.env": "$(capture).env.*",
|
||||||
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
|
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
|
||||||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
|
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
|
||||||
"oxlint.config.ts": ".eslintignore,.stylelintignore,.commitlintrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml,oxfmt.config.*,eslint.config.*"
|
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml",
|
||||||
|
"tailwind.config.mjs": "postcss.*"
|
||||||
},
|
},
|
||||||
"commentTranslate.hover.enabled": false,
|
"commentTranslate.hover.enabled": false,
|
||||||
"commentTranslate.multiLineMerge": true,
|
"commentTranslate.multiLineMerge": true,
|
||||||
"vue.server.hybridMode": true
|
"vue.server.hybridMode": true,
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"oxc.enable": false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
84
README.md
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
## 🐶 新手必读
|
## 🐶 新手必读
|
||||||
|
|
||||||
- nodejs >= v22.18.0(推荐v24) && pnpm >= 11.0.0(强制使用 pnpm)
|
- nodejs > v20.19.0 | v22 | v24 && pnpm > 10.20.0 (强制使用pnpm)
|
||||||
- 演示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
|
- 演示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
|
||||||
- 演示地址【Vue3 + vben5(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
|
- 演示地址【Vue3 + vben5(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
|
||||||
- 演示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
|
- 演示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
|
||||||
|
|
@ -20,12 +20,12 @@
|
||||||
|
|
||||||
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
||||||
|
|
||||||
- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5.7.0 实现
|
- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5 实现
|
||||||
- 支持 [Ant Design Vue](https://www.antdv.com/) | [Element Plus](https://element-plus.org/zh-CN/) | [Naive UI](https://www.naiveui.com/) | [TDesign](https://tdesign.tencent.com/) 多种免费开源的中后台模版,具备如下特性:
|
- 支持 [Ant Design Vue](https://www.antdv.com/) | [Element Plus](https://element-plus.org/zh-CN/) | [Naive UI](https://www.naiveui.com/) | [TDesign](https://tdesign.tencent.com/) 多种免费开源的中后台模版,具备如下特性:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
- **最新技术栈**:使用 Vue3、Vite8 等前端前沿技术开发
|
- **最新技术栈**:使用 Vue3、Vite7 等前端前沿技术开发
|
||||||
- **TypeScript**: 应用程序级 JavaScript 的语言
|
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||||
- **主题**: 提供多套主题色彩,可配置自定义主题
|
- **主题**: 提供多套主题色彩,可配置自定义主题
|
||||||
- **国际化**:内置完善的国际化方案
|
- **国际化**:内置完善的国际化方案
|
||||||
|
|
@ -41,24 +41,24 @@
|
||||||
|
|
||||||
| 框架 | 说明 | 版本 |
|
| 框架 | 说明 | 版本 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.35 |
|
| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.27 |
|
||||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 8.0.10 |
|
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 7.3.1 |
|
||||||
| [Ant Design Vue](https://www.antdv.com/) | Ant Design Vue | 4.2.6 |
|
| [Ant Design Vue](https://www.antdv.com/) | Ant Design Vue | 4.2.6 |
|
||||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.14.1 |
|
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.13.1 |
|
||||||
| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.44.1 |
|
| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.43.2 |
|
||||||
| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.20.0 |
|
| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.18.0 |
|
||||||
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 超集 | 6.0.3 |
|
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 超集 | 5.9.3 |
|
||||||
| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.4 |
|
| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.4 |
|
||||||
| [vueuse](https://vueuse.org/) | 常用工具集 | 14.3.0 |
|
| [vueuse](https://vueuse.org/) | 常用工具集 | 14.1.0 |
|
||||||
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.4.4 |
|
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.2.8 |
|
||||||
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 5.1.0 |
|
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.6.4 |
|
||||||
| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 4.3.0 |
|
| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 3.4.19 |
|
||||||
| [Iconify](https://iconify.design/) | 图标组件 | 5.0.1 |
|
| [Iconify](https://iconify.design/) | 图标组件 | 5.0.0 |
|
||||||
| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.481 |
|
| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.431 |
|
||||||
| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 7.3.0 |
|
| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 7.3.0 |
|
||||||
| [Echarts](https://echarts.apache.org/) | 图表库 | 6.1.0 |
|
| [Echarts](https://echarts.apache.org/) | 图表库 | 6.0.0 |
|
||||||
| [axios](https://axios-http.com/) | http客户端 | 1.16.1 |
|
| [axios](https://axios-http.com/) | http客户端 | 1.13.2 |
|
||||||
| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.21 |
|
| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.19 |
|
||||||
| [vee-validate](https://vee-validate.logaretm.com/) | 表单验证 | 4.15.1 |
|
| [vee-validate](https://vee-validate.logaretm.com/) | 表单验证 | 4.15.1 |
|
||||||
| [zod](https://zod.dev/) | 数据验证 | 3.25.76 |
|
| [zod](https://zod.dev/) | 数据验证 | 3.25.76 |
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@
|
||||||
|
|
||||||
- 通用模块(必选):系统功能、基础设施
|
- 通用模块(必选):系统功能、基础设施
|
||||||
- 通用模块(可选):工作流程、支付系统、数据报表、会员中心
|
- 通用模块(可选):工作流程、支付系统、数据报表、会员中心
|
||||||
- 业务系统(按需):Mall 电子商城、OA 办公自动化、ERP 企业资源计划系统、WMS 仓库管理系统、CRM 客户关系管理、CMS 内容管理系统、MES 执行制造系统、AI 大模型平台、IoT 物联网系统、IM 即时通讯系统、Mobile 手机移动端、Report 数据大屏
|
- 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型
|
||||||
|
|
||||||
### 系统功能
|
### 系统功能
|
||||||
|
|
||||||
|
|
@ -219,44 +219,18 @@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### 会员中心
|
|
||||||
|
|
||||||
| | 功能 | 描述 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| 🚀 | 会员管理 | 会员是 C 端的消费者,该功能用于会员的搜索与管理 |
|
|
||||||
| 🚀 | 会员标签 | 对会员的标签进行创建、查询、修改、删除等操作 |
|
|
||||||
| 🚀 | 会员等级 | 对会员的等级、成长值进行管理,可用于订单折扣等会员权益 |
|
|
||||||
| 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 |
|
|
||||||
| 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 |
|
|
||||||
|
|
||||||
### ERP 系统
|
### ERP 系统
|
||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/erp-preview/>
|
演示地址:<https://doc.iocoder.cn/erp-preview/>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### WMS 系统
|
|
||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/wms-preview/>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### CRM 系统
|
### CRM 系统
|
||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/crm-preview/>
|
演示地址:<https://doc.iocoder.cn/crm-preview/>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### MES 系统
|
|
||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/mes-preview/>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### AI 大模型
|
### AI 大模型
|
||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/ai-preview/>
|
演示地址:<https://doc.iocoder.cn/ai-preview/>
|
||||||
|
|
@ -264,23 +238,3 @@
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### IoT 物联网
|
|
||||||
|
|
||||||
演示地址:<https://doc.iocoder.cn/iot/build>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### IM 即时通讯
|
|
||||||
|
|
||||||
演示地址(Vue3 + Vben5):<http://dashboard-vben.yudao.iocoder.cn>
|
|
||||||
|
|
||||||
使用文档:<https://doc.iocoder.cn/im-preview/>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
| 聊天界面 | 聊天管理 |
|
|
||||||
| --- | --- |
|
|
||||||
|  |  |
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||||
/>
|
/>
|
||||||
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
|
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
|
||||||
<title>%VITE_APP_TITLE%</title>
|
<title><%= VITE_APP_TITLE %></title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<script>
|
<script>
|
||||||
var HM_ID = '<%= VITE_APP_BAIDU_CODE %>';
|
var HM_ID = '<%= VITE_APP_BAIDU_CODE %>';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@vben/web-antd",
|
"name": "@vben/web-antd",
|
||||||
"version": "5.7.0",
|
"version": "5.5.9",
|
||||||
"homepage": "https://vben.pro",
|
"homepage": "https://vben.pro",
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"build:analyze": "pnpm vite build --mode analyze",
|
"build:analyze": "pnpm vite build --mode analyze",
|
||||||
"dev": "pnpm vite --mode development",
|
"dev": "pnpm vite --mode development",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"typecheck": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vue-tsc --noEmit --skipLibCheck --incremental --tsBuildInfoFile node_modules/.cache/vue-tsc/tsconfig.tsbuildinfo"
|
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
"#/*": "./src/*"
|
"#/*": "./src/*"
|
||||||
|
|
@ -54,15 +54,12 @@
|
||||||
"camunda-bpmn-moddle": "catalog:",
|
"camunda-bpmn-moddle": "catalog:",
|
||||||
"cropperjs": "catalog:",
|
"cropperjs": "catalog:",
|
||||||
"dayjs": "catalog:",
|
"dayjs": "catalog:",
|
||||||
"dhtmlx-gantt": "catalog:",
|
|
||||||
"diagram-js": "catalog:",
|
"diagram-js": "catalog:",
|
||||||
"fast-xml-parser": "catalog:",
|
"fast-xml-parser": "catalog:",
|
||||||
"highlight.js": "catalog:",
|
"highlight.js": "catalog:",
|
||||||
"livekit-client": "catalog:",
|
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
"steady-xml": "catalog:",
|
"steady-xml": "catalog:",
|
||||||
"tinymce": "catalog:",
|
"tinymce": "catalog:",
|
||||||
"tyme4ts": "catalog:",
|
|
||||||
"video.js": "catalog:",
|
"video.js": "catalog:",
|
||||||
"vue": "catalog:",
|
"vue": "catalog:",
|
||||||
"vue-dompurify-html": "catalog:",
|
"vue-dompurify-html": "catalog:",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from '@vben/tailwind-config/postcss';
|
||||||
|
|
@ -2537,12 +2537,12 @@ interface EditorSelection {
|
||||||
normalize: () => Range;
|
normalize: () => Range;
|
||||||
selectorChanged: (selector: string, callback: (active: boolean, args: {
|
selectorChanged: (selector: string, callback: (active: boolean, args: {
|
||||||
node: Node;
|
node: Node;
|
||||||
selector: string;
|
selector: String;
|
||||||
parents: Node[];
|
parents: Node[];
|
||||||
}) => void) => EditorSelection;
|
}) => void) => EditorSelection;
|
||||||
selectorChangedWithUnbind: (selector: string, callback: (active: boolean, args: {
|
selectorChangedWithUnbind: (selector: string, callback: (active: boolean, args: {
|
||||||
node: Node;
|
node: Node;
|
||||||
selector: string;
|
selector: String;
|
||||||
parents: Node[];
|
parents: Node[];
|
||||||
}) => void) => {
|
}) => void) => {
|
||||||
unbind: () => void;
|
unbind: () => void;
|
||||||
|
|
@ -3217,9 +3217,9 @@ interface Tools {
|
||||||
<T, R>(arr: ArrayLike<T> | null | undefined, cb: ArrayCallback<T, R>): R[];
|
<T, R>(arr: ArrayLike<T> | null | undefined, cb: ArrayCallback<T, R>): R[];
|
||||||
<T, R>(obj: Record<string, T> | null | undefined, cb: ObjCallback<T, R>): R[];
|
<T, R>(obj: Record<string, T> | null | undefined, cb: ObjCallback<T, R>): R[];
|
||||||
};
|
};
|
||||||
extend: (obj: object, ext: object, ...objs: object[]) => any;
|
extend: (obj: Object, ext: Object, ...objs: Object[]) => any;
|
||||||
walk: <T extends Record<string, any>>(obj: T, f: WalkCallback<T>, n?: keyof T, scope?: any) => void;
|
walk: <T extends Record<string, any>>(obj: T, f: WalkCallback<T>, n?: keyof T, scope?: any) => void;
|
||||||
resolve: (path: string, o?: object) => any;
|
resolve: (path: string, o?: Object) => any;
|
||||||
explode: (s: string | string[], d?: string | RegExp) => string[];
|
explode: (s: string | string[], d?: string | RegExp) => string[];
|
||||||
_addCacheSuffix: (url: string) => string;
|
_addCacheSuffix: (url: string) => string;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,39 +6,14 @@
|
||||||
/* eslint-disable vue/one-component-per-file */
|
/* eslint-disable vue/one-component-per-file */
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AutoCompleteProps,
|
|
||||||
ButtonProps,
|
|
||||||
CascaderProps,
|
|
||||||
CheckboxGroupProps,
|
|
||||||
CheckboxProps,
|
|
||||||
DatePickerProps,
|
|
||||||
DividerProps,
|
|
||||||
InputNumberProps,
|
|
||||||
InputProps,
|
|
||||||
MentionsProps,
|
|
||||||
RadioGroupProps,
|
|
||||||
RadioProps,
|
|
||||||
RateProps,
|
|
||||||
SelectProps,
|
|
||||||
SpaceProps,
|
|
||||||
SwitchProps,
|
|
||||||
TextAreaProps,
|
|
||||||
TimePickerProps,
|
|
||||||
TreeSelectProps,
|
|
||||||
UploadChangeParam,
|
UploadChangeParam,
|
||||||
UploadFile,
|
UploadFile,
|
||||||
UploadProps,
|
UploadProps,
|
||||||
} from 'ant-design-vue';
|
} from 'ant-design-vue';
|
||||||
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
|
|
||||||
|
|
||||||
import type { Component, Ref } from 'vue';
|
import type { Component, Ref } from 'vue';
|
||||||
|
|
||||||
import type {
|
import type { BaseFormComponentType } from '@vben/common-ui';
|
||||||
ApiComponentSharedProps,
|
|
||||||
BaseFormComponentType,
|
|
||||||
IconPickerProps,
|
|
||||||
} from '@vben/common-ui';
|
|
||||||
import type { Sortable } from '@vben/hooks';
|
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -46,9 +21,6 @@ import {
|
||||||
defineAsyncComponent,
|
defineAsyncComponent,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
h,
|
h,
|
||||||
nextTick,
|
|
||||||
onMounted,
|
|
||||||
onUnmounted,
|
|
||||||
ref,
|
ref,
|
||||||
render,
|
render,
|
||||||
unref,
|
unref,
|
||||||
|
|
@ -61,7 +33,6 @@ import {
|
||||||
IconPicker,
|
IconPicker,
|
||||||
VCropper,
|
VCropper,
|
||||||
} from '@vben/common-ui';
|
} from '@vben/common-ui';
|
||||||
import { useSortable } from '@vben/hooks';
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import { isEmpty } from '@vben/utils';
|
import { isEmpty } from '@vben/utils';
|
||||||
|
|
@ -70,15 +41,6 @@ import { message, Modal, notification } from 'ant-design-vue';
|
||||||
|
|
||||||
import { Tinymce as RichTextarea } from '#/components/tinymce';
|
import { Tinymce as RichTextarea } from '#/components/tinymce';
|
||||||
import { FileUpload, ImageUpload } from '#/components/upload';
|
import { FileUpload, ImageUpload } from '#/components/upload';
|
||||||
type AdapterUploadProps = UploadProps & {
|
|
||||||
aspectRatio?: string;
|
|
||||||
crop?: boolean;
|
|
||||||
draggable?: boolean;
|
|
||||||
handleChange?: (event: UploadChangeParam) => void;
|
|
||||||
maxSize?: number;
|
|
||||||
onDragSort?: (oldIndex: number, newIndex: number) => void;
|
|
||||||
onHandleChange?: (event: UploadChangeParam) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const AutoComplete = defineAsyncComponent(
|
const AutoComplete = defineAsyncComponent(
|
||||||
() => import('ant-design-vue/es/auto-complete'),
|
() => import('ant-design-vue/es/auto-complete'),
|
||||||
|
|
@ -136,8 +98,8 @@ const PreviewGroup = defineAsyncComponent(() =>
|
||||||
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
||||||
);
|
);
|
||||||
|
|
||||||
const withDefaultPlaceholder = (
|
const withDefaultPlaceholder = <T extends Component>(
|
||||||
component: Component,
|
component: T,
|
||||||
type: 'input' | 'select',
|
type: 'input' | 'select',
|
||||||
componentProps: Recordable<any> = {},
|
componentProps: Recordable<any> = {},
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -170,261 +132,260 @@ const withDefaultPlaceholder = (
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const IMAGE_EXTENSIONS = new Set([
|
const withPreviewUpload = () => {
|
||||||
'bmp',
|
// 检查是否为图片文件的辅助函数
|
||||||
'gif',
|
const isImageFile = (file: UploadFile): boolean => {
|
||||||
'jpeg',
|
const imageExtensions = new Set([
|
||||||
'jpg',
|
'bmp',
|
||||||
'png',
|
'gif',
|
||||||
'svg',
|
'jpeg',
|
||||||
'webp',
|
'jpg',
|
||||||
]);
|
'png',
|
||||||
|
'svg',
|
||||||
/**
|
'webp',
|
||||||
* 检查是否为图片文件
|
]);
|
||||||
*/
|
if (file.url) {
|
||||||
function isImageFile(file: UploadFile): boolean {
|
try {
|
||||||
if (file.url) {
|
const pathname = new URL(file.url, 'http://localhost').pathname;
|
||||||
try {
|
const ext = pathname.split('.').pop()?.toLowerCase();
|
||||||
const pathname = new URL(file.url, 'http://localhost').pathname;
|
return ext ? imageExtensions.has(ext) : false;
|
||||||
const ext = pathname.split('.').pop()?.toLowerCase();
|
} catch {
|
||||||
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
|
const ext = file.url?.split('.').pop()?.toLowerCase();
|
||||||
} catch {
|
return ext ? imageExtensions.has(ext) : false;
|
||||||
const ext = file.url?.split('.').pop()?.toLowerCase();
|
}
|
||||||
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
|
|
||||||
}
|
}
|
||||||
}
|
if (!file.type) {
|
||||||
if (!file.type) {
|
const ext = file.name?.split('.').pop()?.toLowerCase();
|
||||||
const ext = file.name?.split('.').pop()?.toLowerCase();
|
return ext ? imageExtensions.has(ext) : false;
|
||||||
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
|
}
|
||||||
}
|
return file.type.startsWith('image/');
|
||||||
return file.type.startsWith('image/');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建默认的上传按钮插槽
|
|
||||||
*/
|
|
||||||
function createDefaultUploadSlots(listType: string, placeholder: string) {
|
|
||||||
if (listType === 'picture-card') {
|
|
||||||
return { default: () => placeholder };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
default: () =>
|
|
||||||
h(
|
|
||||||
Button,
|
|
||||||
{
|
|
||||||
icon: h(IconifyIcon, {
|
|
||||||
icon: 'ant-design:upload-outlined',
|
|
||||||
class: 'mb-1 size-4',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
() => placeholder,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
// 创建默认的上传按钮插槽
|
||||||
|
const createDefaultSlotsWithUpload = (
|
||||||
/**
|
listType: string,
|
||||||
* 获取文件的 Base64
|
placeholder: string,
|
||||||
*/
|
) => {
|
||||||
function getBase64(file: File): Promise<string> {
|
switch (listType) {
|
||||||
return new Promise((resolve, reject) => {
|
case 'picture-card': {
|
||||||
const reader = new FileReader();
|
return {
|
||||||
reader.readAsDataURL(file);
|
default: () => placeholder,
|
||||||
reader.addEventListener('load', () => resolve(reader.result as string));
|
};
|
||||||
reader.addEventListener('error', reject);
|
}
|
||||||
});
|
default: {
|
||||||
}
|
return {
|
||||||
|
default: () =>
|
||||||
/**
|
h(
|
||||||
* 预览图片
|
Button,
|
||||||
*/
|
{
|
||||||
async function previewImage(
|
icon: h(IconifyIcon, {
|
||||||
file: UploadFile,
|
icon: 'ant-design:upload-outlined',
|
||||||
visible: Ref<boolean>,
|
class: 'mb-1 size-4',
|
||||||
fileList: Ref<UploadProps['fileList']>,
|
}),
|
||||||
) {
|
|
||||||
// 非图片文件直接打开链接
|
|
||||||
if (!isImageFile(file)) {
|
|
||||||
const url = file.url || file.preview;
|
|
||||||
if (url) {
|
|
||||||
window.open(url, '_blank');
|
|
||||||
} else {
|
|
||||||
message.error($t('ui.formRules.previewWarning'));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [ImageComponent, PreviewGroupComponent] = await Promise.all([
|
|
||||||
Image,
|
|
||||||
PreviewGroup,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 过滤图片文件并生成预览
|
|
||||||
const imageFiles = (unref(fileList) || []).filter((f) => isImageFile(f));
|
|
||||||
|
|
||||||
for (const imgFile of imageFiles) {
|
|
||||||
if (!imgFile.url && !imgFile.preview && imgFile.originFileObj) {
|
|
||||||
imgFile.preview = await getBase64(imgFile.originFileObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const container = document.createElement('div');
|
|
||||||
document.body.append(container);
|
|
||||||
let isUnmounted = false;
|
|
||||||
|
|
||||||
const currentIndex = imageFiles.findIndex((f) => f.uid === file.uid);
|
|
||||||
|
|
||||||
const PreviewWrapper = {
|
|
||||||
setup() {
|
|
||||||
return () => {
|
|
||||||
if (isUnmounted) return null;
|
|
||||||
return h(
|
|
||||||
PreviewGroupComponent,
|
|
||||||
{
|
|
||||||
class: 'hidden',
|
|
||||||
preview: {
|
|
||||||
visible: visible.value,
|
|
||||||
current: currentIndex,
|
|
||||||
onVisibleChange: (value: boolean) => {
|
|
||||||
visible.value = value;
|
|
||||||
if (!value) {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!isUnmounted && container) {
|
|
||||||
isUnmounted = true;
|
|
||||||
render(null, container);
|
|
||||||
container.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
() => placeholder,
|
||||||
},
|
|
||||||
() =>
|
|
||||||
imageFiles.map((imgFile) =>
|
|
||||||
h(ImageComponent, {
|
|
||||||
key: imgFile.uid,
|
|
||||||
src: imgFile.url || imgFile.preview,
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
);
|
};
|
||||||
};
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
// 构建预览图片组
|
||||||
|
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 {
|
||||||
|
message.error($t('ui.formRules.previewWarning'));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
render(h(PreviewWrapper), container);
|
// 对于图片文件,继续使用预览组
|
||||||
}
|
const [ImageComponent, PreviewGroupComponent] = await Promise.all([
|
||||||
|
Image,
|
||||||
|
PreviewGroup,
|
||||||
|
]);
|
||||||
|
|
||||||
/**
|
const getBase64 = (file: File) => {
|
||||||
* 图片裁剪操作
|
return new Promise((resolve, reject) => {
|
||||||
*/
|
const reader = new FileReader();
|
||||||
function cropImage(file: File, aspectRatio: string | undefined) {
|
reader.readAsDataURL(file);
|
||||||
return new Promise<Blob | string | undefined>((resolve, reject) => {
|
reader.addEventListener('load', () => resolve(reader.result));
|
||||||
const container = document.createElement('div');
|
reader.addEventListener('error', (error) => reject(error));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 从fileList中过滤出所有图片文件
|
||||||
|
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);
|
document.body.append(container);
|
||||||
|
|
||||||
|
// 用于追踪组件是否已卸载
|
||||||
let isUnmounted = false;
|
let isUnmounted = false;
|
||||||
let objectUrl: null | string = null;
|
|
||||||
|
|
||||||
const open = ref<boolean>(true);
|
const PreviewWrapper = {
|
||||||
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
|
|
||||||
|
|
||||||
const closeModal = () => {
|
|
||||||
open.value = false;
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!isUnmounted && container) {
|
|
||||||
if (objectUrl) {
|
|
||||||
URL.revokeObjectURL(objectUrl);
|
|
||||||
}
|
|
||||||
isUnmounted = true;
|
|
||||||
render(null, container);
|
|
||||||
container.remove();
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
};
|
|
||||||
|
|
||||||
const CropperWrapper = {
|
|
||||||
setup() {
|
setup() {
|
||||||
return () => {
|
return () => {
|
||||||
if (isUnmounted) return null;
|
if (isUnmounted) return null;
|
||||||
if (!objectUrl) {
|
|
||||||
objectUrl = URL.createObjectURL(file);
|
|
||||||
}
|
|
||||||
return h(
|
return h(
|
||||||
Modal,
|
PreviewGroupComponent,
|
||||||
{
|
{
|
||||||
open: open.value,
|
class: 'hidden',
|
||||||
title: h('div', {}, [
|
preview: {
|
||||||
$t('ui.crop.title'),
|
visible: visible.value,
|
||||||
h(
|
// 设置初始显示的图片索引
|
||||||
'span',
|
current: imageFiles.findIndex((f) => f.uid === file.uid),
|
||||||
{
|
onVisibleChange: (value: boolean) => {
|
||||||
class: `${aspectRatio ? '' : 'hidden'} ml-2 text-sm text-gray-400 font-normal`,
|
visible.value = value;
|
||||||
},
|
if (!value) {
|
||||||
$t('ui.crop.titleTip', [aspectRatio]),
|
// 延迟清理,确保动画完成
|
||||||
),
|
setTimeout(() => {
|
||||||
]),
|
if (!isUnmounted && container) {
|
||||||
centered: true,
|
isUnmounted = true;
|
||||||
width: 548,
|
render(null, container);
|
||||||
keyboard: false,
|
container.remove();
|
||||||
maskClosable: false,
|
}
|
||||||
closable: false,
|
}, 300);
|
||||||
cancelText: $t('common.cancel'),
|
|
||||||
okText: $t('ui.crop.confirm'),
|
|
||||||
destroyOnClose: true,
|
|
||||||
onOk: async () => {
|
|
||||||
const cropper = cropperRef.value;
|
|
||||||
if (!cropper) {
|
|
||||||
reject(new Error('Cropper not found'));
|
|
||||||
closeModal();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const dataUrl = await cropper.getCropImage();
|
|
||||||
if (dataUrl) {
|
|
||||||
resolve(dataUrl);
|
|
||||||
} else {
|
|
||||||
reject(new Error($t('ui.crop.errorTip')));
|
|
||||||
}
|
}
|
||||||
} catch {
|
},
|
||||||
reject(new Error($t('ui.crop.errorTip')));
|
|
||||||
} finally {
|
|
||||||
closeModal();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
resolve('');
|
|
||||||
closeModal();
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
() =>
|
() =>
|
||||||
h(VCropper, {
|
// 渲染所有图片文件
|
||||||
ref: (ref: any) => (cropperRef.value = ref),
|
imageFiles.map((imgFile) =>
|
||||||
img: objectUrl as string,
|
h(ImageComponent, {
|
||||||
aspectRatio,
|
key: imgFile.uid,
|
||||||
}),
|
src: imgFile.url || imgFile.preview,
|
||||||
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
render(h(CropperWrapper), container);
|
render(h(PreviewWrapper), container);
|
||||||
});
|
};
|
||||||
}
|
|
||||||
|
// 图片裁剪操作
|
||||||
|
const cropImage = (file: File, aspectRatio: string | undefined) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const container: HTMLElement | null = document.createElement('div');
|
||||||
|
document.body.append(container);
|
||||||
|
|
||||||
|
// 用于追踪组件是否已卸载
|
||||||
|
let isUnmounted = false;
|
||||||
|
let objectUrl: null | string = null;
|
||||||
|
|
||||||
|
const open = ref<boolean>(true);
|
||||||
|
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
open.value = false;
|
||||||
|
// 延迟清理,确保动画完成
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!isUnmounted && container) {
|
||||||
|
if (objectUrl) {
|
||||||
|
URL.revokeObjectURL(objectUrl);
|
||||||
|
}
|
||||||
|
isUnmounted = true;
|
||||||
|
render(null, container);
|
||||||
|
container.remove();
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CropperWrapper = {
|
||||||
|
setup() {
|
||||||
|
return () => {
|
||||||
|
if (isUnmounted) return null;
|
||||||
|
if (!objectUrl) {
|
||||||
|
objectUrl = URL.createObjectURL(file);
|
||||||
|
}
|
||||||
|
return h(
|
||||||
|
Modal,
|
||||||
|
{
|
||||||
|
open: open.value,
|
||||||
|
title: h('div', {}, [
|
||||||
|
$t('ui.crop.title'),
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
|
class: `${aspectRatio ? '' : 'hidden'} ml-2 text-sm text-gray-400 font-normal`,
|
||||||
|
},
|
||||||
|
$t('ui.crop.titleTip', [aspectRatio]),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
centered: true,
|
||||||
|
width: 548,
|
||||||
|
keyboard: false,
|
||||||
|
maskClosable: false,
|
||||||
|
closable: false,
|
||||||
|
cancelText: $t('common.cancel'),
|
||||||
|
okText: $t('ui.crop.confirm'),
|
||||||
|
destroyOnClose: true,
|
||||||
|
onOk: async () => {
|
||||||
|
const cropper = cropperRef.value;
|
||||||
|
if (!cropper) {
|
||||||
|
reject(new Error('Cropper not found'));
|
||||||
|
closeModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const dataUrl = await cropper.getCropImage();
|
||||||
|
resolve(dataUrl);
|
||||||
|
} catch {
|
||||||
|
reject(new Error($t('ui.crop.errorTip')));
|
||||||
|
} finally {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
resolve('');
|
||||||
|
closeModal();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
h(VCropper, {
|
||||||
|
ref: (ref: any) => (cropperRef.value = ref),
|
||||||
|
img: objectUrl as string,
|
||||||
|
aspectRatio,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
render(h(CropperWrapper), container);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 带预览功能的上传组件
|
|
||||||
*/
|
|
||||||
const withPreviewUpload = () => {
|
|
||||||
return defineComponent({
|
return defineComponent({
|
||||||
name: Upload.name,
|
name: Upload.name,
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
setup(
|
setup: (
|
||||||
props: any,
|
props: any,
|
||||||
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
|
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
|
||||||
) {
|
) => {
|
||||||
const previewVisible = ref<boolean>(false);
|
const previewVisible = ref<boolean>(false);
|
||||||
const placeholder = attrs?.placeholder || $t('ui.placeholder.upload');
|
|
||||||
|
const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`);
|
||||||
|
|
||||||
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
|
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
|
||||||
|
|
||||||
const fileList = ref<UploadProps['fileList']>(
|
const fileList = ref<UploadProps['fileList']>(
|
||||||
attrs?.fileList || attrs?.['file-list'] || [],
|
attrs?.fileList || attrs?.['file-list'] || [],
|
||||||
);
|
);
|
||||||
|
|
@ -438,14 +399,12 @@ const withPreviewUpload = () => {
|
||||||
file: UploadFile,
|
file: UploadFile,
|
||||||
originFileList: Array<File>,
|
originFileList: Array<File>,
|
||||||
) => {
|
) => {
|
||||||
// 文件大小限制
|
|
||||||
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
||||||
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
||||||
file.status = 'removed';
|
file.status = 'removed';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// 多选或者非图片不唤起裁剪框
|
||||||
// 图片裁剪处理
|
|
||||||
if (
|
if (
|
||||||
attrs.crop &&
|
attrs.crop &&
|
||||||
!attrs.multiple &&
|
!attrs.multiple &&
|
||||||
|
|
@ -453,11 +412,14 @@ const withPreviewUpload = () => {
|
||||||
isImageFile(file)
|
isImageFile(file)
|
||||||
) {
|
) {
|
||||||
file.status = 'removed';
|
file.status = 'removed';
|
||||||
|
// antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取
|
||||||
const blob = await cropImage(originFileList[0], aspectRatio.value);
|
const blob = await cropImage(originFileList[0], aspectRatio.value);
|
||||||
if (!blob) {
|
return new Promise((resolve, reject) => {
|
||||||
throw new Error($t('ui.crop.errorTip'));
|
if (!blob) {
|
||||||
}
|
return reject(new Error($t('ui.crop.errorTip')));
|
||||||
return blob;
|
}
|
||||||
|
resolve(blob);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return attrs.beforeUpload?.(file) ?? true;
|
return attrs.beforeUpload?.(file) ?? true;
|
||||||
|
|
@ -465,9 +427,12 @@ const withPreviewUpload = () => {
|
||||||
|
|
||||||
const handleChange = (event: UploadChangeParam) => {
|
const handleChange = (event: UploadChangeParam) => {
|
||||||
try {
|
try {
|
||||||
|
// 行内写法 handleChange: (event) => {}
|
||||||
attrs.handleChange?.(event);
|
attrs.handleChange?.(event);
|
||||||
|
// template写法 @handle-change="(event) => {}"
|
||||||
attrs.onHandleChange?.(event);
|
attrs.onHandleChange?.(event);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Avoid breaking internal v-model sync on user handler errors
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
fileList.value = event.fileList.filter(
|
fileList.value = event.fileList.filter(
|
||||||
|
|
@ -484,88 +449,21 @@ const withPreviewUpload = () => {
|
||||||
await previewImage(file, previewVisible, fileList);
|
await previewImage(file, previewVisible, fileList);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderUploadButton = () => {
|
const renderUploadButton = (): any => {
|
||||||
if (attrs.disabled) return null;
|
const isDisabled = attrs.disabled;
|
||||||
|
|
||||||
|
// 如果禁用,不渲染上传按钮
|
||||||
|
if (isDisabled) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则渲染默认上传按钮
|
||||||
return isEmpty(slots)
|
return isEmpty(slots)
|
||||||
? createDefaultUploadSlots(listType, placeholder)
|
? createDefaultSlotsWithUpload(listType, placeholder)
|
||||||
: slots;
|
: slots;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 拖拽排序
|
// 可以监听到表单API设置的值
|
||||||
const draggable = computed(
|
|
||||||
() => (attrs.draggable ?? false) && !attrs.disabled,
|
|
||||||
);
|
|
||||||
const uploadId = `upload-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
||||||
const sortableInstance = ref<null | Sortable>(null);
|
|
||||||
|
|
||||||
const styleId = `upload-drag-style-${uploadId}`;
|
|
||||||
|
|
||||||
function injectDragStyle() {
|
|
||||||
if (!document.querySelector(`[id="${styleId}"]`)) {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.id = styleId;
|
|
||||||
style.textContent = `
|
|
||||||
[data-upload-id="${uploadId}"] .ant-upload-list-item { cursor: move; }
|
|
||||||
[data-upload-id="${uploadId}"] .ant-upload-list-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
|
|
||||||
`;
|
|
||||||
document.head.append(style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeDragStyle() {
|
|
||||||
document.querySelector(`[id="${styleId}"]`)?.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function initSortable(retryCount = 0) {
|
|
||||||
if (!draggable.value) return;
|
|
||||||
|
|
||||||
injectDragStyle();
|
|
||||||
await nextTick();
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
||||||
|
|
||||||
const container = document.querySelector(
|
|
||||||
`[data-upload-id="${uploadId}"] .ant-upload-list`,
|
|
||||||
) as HTMLElement;
|
|
||||||
|
|
||||||
if (!container) {
|
|
||||||
if (retryCount < 5) {
|
|
||||||
setTimeout(() => initSortable(retryCount + 1), 200);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { initializeSortable } = useSortable(container, {
|
|
||||||
animation: 300,
|
|
||||||
delay: 400,
|
|
||||||
delayOnTouchOnly: true,
|
|
||||||
filter:
|
|
||||||
'.ant-upload-select, .ant-upload-list-item-error, .ant-upload-list-item-uploading',
|
|
||||||
onEnd: (evt) => {
|
|
||||||
const { oldIndex, newIndex } = evt;
|
|
||||||
if (
|
|
||||||
oldIndex === undefined ||
|
|
||||||
newIndex === undefined ||
|
|
||||||
oldIndex === newIndex
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const list = [...(fileList.value || [])];
|
|
||||||
const [movedItem] = list.splice(oldIndex, 1);
|
|
||||||
if (movedItem) {
|
|
||||||
list.splice(newIndex, 0, movedItem);
|
|
||||||
fileList.value = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs.onDragSort?.(oldIndex, newIndex);
|
|
||||||
emit('update:modelValue', fileList.value);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
sortableInstance.value = await initializeSortable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听表单值变化
|
|
||||||
watch(
|
watch(
|
||||||
() => attrs.modelValue,
|
() => attrs.modelValue,
|
||||||
(res) => {
|
(res) => {
|
||||||
|
|
@ -573,28 +471,18 @@ const withPreviewUpload = () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(initSortable);
|
|
||||||
onUnmounted(() => {
|
|
||||||
sortableInstance.value?.destroy();
|
|
||||||
removeDragStyle();
|
|
||||||
});
|
|
||||||
|
|
||||||
return () =>
|
return () =>
|
||||||
h(
|
h(
|
||||||
'div',
|
Upload,
|
||||||
{ 'data-upload-id': uploadId, class: 'w-full' },
|
{
|
||||||
h(
|
...props,
|
||||||
Upload,
|
...attrs,
|
||||||
{
|
fileList: fileList.value,
|
||||||
...props,
|
beforeUpload: handleBeforeUpload,
|
||||||
...attrs,
|
onChange: handleChange,
|
||||||
fileList: fileList.value,
|
onPreview: handlePreview,
|
||||||
beforeUpload: handleBeforeUpload,
|
},
|
||||||
onChange: handleChange,
|
renderUploadButton(),
|
||||||
onPreview: handlePreview,
|
|
||||||
},
|
|
||||||
renderUploadButton() as any,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -635,39 +523,6 @@ export type ComponentType =
|
||||||
| 'Upload'
|
| 'Upload'
|
||||||
| BaseFormComponentType;
|
| BaseFormComponentType;
|
||||||
|
|
||||||
/**
|
|
||||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
|
||||||
*/
|
|
||||||
export interface ComponentPropsMap {
|
|
||||||
ApiCascader: ApiComponentSharedProps & CascaderProps;
|
|
||||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
|
||||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
|
||||||
AutoComplete: AutoCompleteProps;
|
|
||||||
Cascader: CascaderProps;
|
|
||||||
Checkbox: CheckboxProps;
|
|
||||||
CheckboxGroup: CheckboxGroupProps;
|
|
||||||
DatePicker: DatePickerProps;
|
|
||||||
DefaultButton: ButtonProps;
|
|
||||||
Divider: DividerProps;
|
|
||||||
IconPicker: IconPickerProps;
|
|
||||||
Input: InputProps;
|
|
||||||
InputNumber: InputNumberProps;
|
|
||||||
InputPassword: InputProps;
|
|
||||||
Mentions: MentionsProps;
|
|
||||||
PrimaryButton: ButtonProps;
|
|
||||||
Radio: RadioProps;
|
|
||||||
RadioGroup: RadioGroupProps;
|
|
||||||
RangePicker: RangePickerProps;
|
|
||||||
Rate: RateProps;
|
|
||||||
Select: SelectProps;
|
|
||||||
Space: SpaceProps;
|
|
||||||
Switch: SwitchProps;
|
|
||||||
Textarea: TextAreaProps;
|
|
||||||
TimePicker: TimePickerProps;
|
|
||||||
TreeSelect: TreeSelectProps;
|
|
||||||
Upload: AdapterUploadProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function initComponentAdapter() {
|
async function initComponentAdapter() {
|
||||||
const components: Partial<Record<ComponentType, Component>> = {
|
const components: Partial<Record<ComponentType, Component>> = {
|
||||||
// 如果你的组件体积比较大,可以使用异步加载
|
// 如果你的组件体积比较大,可以使用异步加载
|
||||||
|
|
@ -711,9 +566,7 @@ async function initComponentAdapter() {
|
||||||
modelValueProp: 'value',
|
modelValueProp: 'value',
|
||||||
}),
|
}),
|
||||||
Input: withDefaultPlaceholder(Input, 'input'),
|
Input: withDefaultPlaceholder(Input, 'input'),
|
||||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||||
style: { width: '100%' },
|
|
||||||
}),
|
|
||||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||||
// 自定义主要按钮
|
// 自定义主要按钮
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import type {
|
import type {
|
||||||
VbenFormProps as FormProps,
|
|
||||||
VbenFormSchema as FormSchema,
|
VbenFormSchema as FormSchema,
|
||||||
|
VbenFormProps,
|
||||||
} from '@vben/common-ui';
|
} from '@vben/common-ui';
|
||||||
|
|
||||||
import type { ComponentPropsMap, ComponentType } from './component';
|
import type { ComponentType } from './component';
|
||||||
|
|
||||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
|
|
@ -61,10 +61,9 @@ async function initSetupVbenForm() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const useVbenForm = useForm<ComponentType, ComponentPropsMap>;
|
const useVbenForm = useForm<ComponentType>;
|
||||||
|
|
||||||
export { initSetupVbenForm, useVbenForm, z };
|
export { initSetupVbenForm, useVbenForm, z };
|
||||||
|
|
||||||
export type VbenFormApi = ReturnType<typeof useVbenForm>[1]; // add by 芋艿:用于 data.ts 表单 schema 内调用 setFieldValue
|
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||||
export type VbenFormSchema = FormSchema<ComponentType, ComponentPropsMap>;
|
export type { VbenFormProps };
|
||||||
export type VbenFormProps = FormProps<ComponentType, ComponentPropsMap>;
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import type { ComponentPropsMap, ComponentType } from './component';
|
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { h } from 'vue';
|
||||||
|
|
||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
@ -12,7 +10,7 @@ import {
|
||||||
AsyncVxeTable,
|
AsyncVxeTable,
|
||||||
createRequiredValidation,
|
createRequiredValidation,
|
||||||
setupVbenVxeTable,
|
setupVbenVxeTable,
|
||||||
useVbenVxeGrid as useGrid,
|
useVbenVxeGrid,
|
||||||
} from '@vben/plugins/vxe-table';
|
} from '@vben/plugins/vxe-table';
|
||||||
import {
|
import {
|
||||||
erpCountInputFormatter,
|
erpCountInputFormatter,
|
||||||
|
|
@ -201,7 +199,7 @@ setupVbenVxeTable({
|
||||||
vxeUI.renderer.add('CellOperation', {
|
vxeUI.renderer.add('CellOperation', {
|
||||||
renderTableDefault({ attrs, options, props }, { column, row }) {
|
renderTableDefault({ attrs, options, props }, { column, row }) {
|
||||||
const defaultProps = { size: 'small', type: 'link', ...props };
|
const defaultProps = { size: 'small', type: 'link', ...props };
|
||||||
let align: string;
|
let align = 'end';
|
||||||
switch (column.align) {
|
switch (column.align) {
|
||||||
case 'center': {
|
case 'center': {
|
||||||
align = 'center';
|
align = 'center';
|
||||||
|
|
@ -365,13 +363,10 @@ setupVbenVxeTable({
|
||||||
useVbenForm,
|
useVbenForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
export { createRequiredValidation };
|
export { createRequiredValidation, useVbenVxeGrid };
|
||||||
|
|
||||||
export const [VxeTable, VxeColumn] = [AsyncVxeTable, AsyncVxeColumn];
|
export const [VxeTable, VxeColumn] = [AsyncVxeTable, AsyncVxeColumn];
|
||||||
|
|
||||||
export * from '#/components/table-action';
|
export * from '#/components/table-action';
|
||||||
export const useVbenVxeGrid = <T extends Record<string, any>>(
|
|
||||||
...rest: Parameters<typeof useGrid<T, ComponentType, ComponentPropsMap>>
|
|
||||||
) => useGrid<T, ComponentType, ComponentPropsMap>(...rest);
|
|
||||||
|
|
||||||
export type * from '@vben/plugins/vxe-table';
|
export type * from '@vben/plugins/vxe-table';
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export namespace AiChatConversationApi {
|
||||||
temperature: number; // 温度参数
|
temperature: number; // 温度参数
|
||||||
maxTokens: number; // 单条回复的最大 Token 数量
|
maxTokens: number; // 单条回复的最大 Token 数量
|
||||||
maxContexts: number; // 上下文的最大 Message 数量
|
maxContexts: number; // 上下文的最大 Message 数量
|
||||||
createTime: Date; // 创建时间
|
createTime?: Date; // 创建时间
|
||||||
systemMessage?: string; // 角色设定
|
systemMessage?: string; // 角色设定
|
||||||
modelName?: string; // 模型名字
|
modelName?: string; // 模型名字
|
||||||
roleAvatar?: string; // 角色头像
|
roleAvatar?: string; // 角色头像
|
||||||
|
|
|
||||||
|
|
@ -34,15 +34,15 @@ export namespace AiImageApi {
|
||||||
prompt: string; // 提示词
|
prompt: string; // 提示词
|
||||||
modelId: number; // 模型
|
modelId: number; // 模型
|
||||||
style: string; // 图像生成的风格
|
style: string; // 图像生成的风格
|
||||||
width: number; // 图片宽度
|
width: string; // 图片宽度
|
||||||
height: number; // 图片高度
|
height: string; // 图片高度
|
||||||
options: object; // 绘制参数,Map<String, String>
|
options: object; // 绘制参数,Map<String, String>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ImageMidjourneyImagineReqVO {
|
export interface ImageMidjourneyImagineReqVO {
|
||||||
prompt: string; // 提示词
|
prompt: string; // 提示词
|
||||||
modelId: number; // 模型
|
modelId: number; // 模型
|
||||||
base64Array: string[]; // 参考图 base64 列表
|
base64Array?: string[]; // size不能为空
|
||||||
width: string; // 图片宽度
|
width: string; // 图片宽度
|
||||||
height: string; // 图片高度
|
height: string; // 图片高度
|
||||||
version: string; // 版本
|
version: string; // 版本
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ export namespace BpmOALeaveApi {
|
||||||
startTime: number;
|
startTime: number;
|
||||||
endTime: number;
|
endTime: number;
|
||||||
createTime: Date;
|
createTime: Date;
|
||||||
|
startUserSelectAssignees?: Record<string, string[]>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,6 +21,11 @@ export async function createLeave(data: BpmOALeaveApi.Leave) {
|
||||||
return requestClient.post('/bpm/oa/leave/create', data);
|
return requestClient.post('/bpm/oa/leave/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 更新请假申请 */
|
||||||
|
export async function updateLeave(data: BpmOALeaveApi.Leave) {
|
||||||
|
return requestClient.post('/bpm/oa/leave/update', data);
|
||||||
|
}
|
||||||
|
|
||||||
/** 获得请假申请 */
|
/** 获得请假申请 */
|
||||||
export async function getLeave(id: number) {
|
export async function getLeave(id: number) {
|
||||||
return requestClient.get<BpmOALeaveApi.Leave>(`/bpm/oa/leave/get?id=${id}`);
|
return requestClient.get<BpmOALeaveApi.Leave>(`/bpm/oa/leave/get?id=${id}`);
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ export namespace BpmProcessInstanceApi {
|
||||||
reason: string;
|
reason: string;
|
||||||
signPicUrl: string;
|
signPicUrl: string;
|
||||||
status: number;
|
status: number;
|
||||||
attachments?: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 抄送流程实例 */
|
/** 抄送流程实例 */
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,15 @@ export namespace CrmBusinessStatusApi {
|
||||||
deptNames?: string[];
|
deptNames?: string[];
|
||||||
creator?: string;
|
creator?: string;
|
||||||
createTime?: Date;
|
createTime?: Date;
|
||||||
statuses: BusinessStatusType[];
|
statuses?: BusinessStatusType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 商机状态信息 */
|
/** 商机状态信息 */
|
||||||
export interface BusinessStatusType {
|
export interface BusinessStatusType {
|
||||||
id?: number;
|
id?: number;
|
||||||
name: string;
|
name: string;
|
||||||
percent?: number;
|
percent: number;
|
||||||
endStatus?: number;
|
[x: string]: any;
|
||||||
key?: string;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +43,7 @@ export const DEFAULT_STATUSES = [
|
||||||
name: '无效',
|
name: '无效',
|
||||||
percent: 0,
|
percent: 0,
|
||||||
},
|
},
|
||||||
] satisfies CrmBusinessStatusApi.BusinessStatusType[];
|
];
|
||||||
|
|
||||||
/** 查询商机状态组列表 */
|
/** 查询商机状态组列表 */
|
||||||
export function getBusinessStatusPage(params: PageParam) {
|
export function getBusinessStatusPage(params: PageParam) {
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ export namespace CrmCustomerLimitConfigApi {
|
||||||
|
|
||||||
/** 客户限制配置类型 */
|
/** 客户限制配置类型 */
|
||||||
export enum LimitConfType {
|
export enum LimitConfType {
|
||||||
/** 拥有客户数限制 */
|
|
||||||
CUSTOMER_QUANTITY_LIMIT = 1,
|
|
||||||
/** 锁定客户数限制 */
|
/** 锁定客户数限制 */
|
||||||
CUSTOMER_LOCK_LIMIT = 2,
|
CUSTOMER_LOCK_LIMIT = 2,
|
||||||
|
/** 拥有客户数限制 */
|
||||||
|
CUSTOMER_QUANTITY_LIMIT = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询客户限制配置列表 */
|
/** 查询客户限制配置列表 */
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@ export namespace CrmPermissionApi {
|
||||||
* CRM 业务类型枚举
|
* CRM 业务类型枚举
|
||||||
*/
|
*/
|
||||||
export enum BizTypeEnum {
|
export enum BizTypeEnum {
|
||||||
CRM_CLUE = 1, // 线索
|
|
||||||
CRM_CUSTOMER = 2, // 客户
|
|
||||||
CRM_CONTACT = 3, // 联系人
|
|
||||||
CRM_BUSINESS = 4, // 商机
|
CRM_BUSINESS = 4, // 商机
|
||||||
|
CRM_CLUE = 1, // 线索
|
||||||
|
CRM_CONTACT = 3, // 联系人
|
||||||
CRM_CONTRACT = 5, // 合同
|
CRM_CONTRACT = 5, // 合同
|
||||||
|
CRM_CUSTOMER = 2, // 客户
|
||||||
CRM_PRODUCT = 6, // 产品
|
CRM_PRODUCT = 6, // 产品
|
||||||
CRM_RECEIVABLE = 7, // 回款
|
CRM_RECEIVABLE = 7, // 回款
|
||||||
CRM_RECEIVABLE_PLAN = 8, // 回款计划
|
CRM_RECEIVABLE_PLAN = 8, // 回款计划
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ export namespace CrmReceivableApi {
|
||||||
customerId?: number;
|
customerId?: number;
|
||||||
customerName?: string;
|
customerName?: string;
|
||||||
contractId?: number;
|
contractId?: number;
|
||||||
contractNo?: string;
|
|
||||||
contract?: Contract;
|
contract?: Contract;
|
||||||
auditStatus: number;
|
auditStatus: number;
|
||||||
processInstanceId: number;
|
processInstanceId: number;
|
||||||
|
|
@ -35,11 +34,6 @@ export namespace CrmReceivableApi {
|
||||||
no: string;
|
no: string;
|
||||||
totalPrice: number;
|
totalPrice: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReceivablePageParam extends PageParam {
|
|
||||||
contractId?: number;
|
|
||||||
customerId?: number;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询回款列表 */
|
/** 查询回款列表 */
|
||||||
|
|
@ -51,9 +45,7 @@ export function getReceivablePage(params: PageParam) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询回款列表,基于指定客户 */
|
/** 查询回款列表,基于指定客户 */
|
||||||
export function getReceivablePageByCustomer(
|
export function getReceivablePageByCustomer(params: PageParam) {
|
||||||
params: CrmReceivableApi.ReceivablePageParam,
|
|
||||||
) {
|
|
||||||
return requestClient.get<PageResult<CrmReceivableApi.Receivable>>(
|
return requestClient.get<PageResult<CrmReceivableApi.Receivable>>(
|
||||||
'/crm/receivable/page-by-customer',
|
'/crm/receivable/page-by-customer',
|
||||||
{ params },
|
{ params },
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,6 @@ export namespace CrmReceivablePlanApi {
|
||||||
returnTime: Date;
|
returnTime: Date;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
export interface PlanPageParam extends PageParam {
|
|
||||||
customerId?: number;
|
|
||||||
contractId?: number;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询回款计划列表 */
|
/** 查询回款计划列表 */
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ export namespace ErpPurchaseInApi {
|
||||||
export interface PurchaseInItem {
|
export interface PurchaseInItem {
|
||||||
count?: number;
|
count?: number;
|
||||||
id?: number;
|
id?: number;
|
||||||
seq?: number; // 前端行号
|
|
||||||
orderItemId?: number;
|
orderItemId?: number;
|
||||||
productBarCode?: string;
|
productBarCode?: string;
|
||||||
productId?: number;
|
productId?: number;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ export namespace ErpPurchaseOrderApi {
|
||||||
/** 采购订单项信息 */
|
/** 采购订单项信息 */
|
||||||
export interface PurchaseOrderItem {
|
export interface PurchaseOrderItem {
|
||||||
id?: number; // 订单项编号
|
id?: number; // 订单项编号
|
||||||
seq?: number; // 前端行号
|
|
||||||
orderId?: number; // 采购订单编号
|
orderId?: number; // 采购订单编号
|
||||||
productId?: number; // 产品编号
|
productId?: number; // 产品编号
|
||||||
productName?: string; // 产品名称
|
productName?: string; // 产品名称
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ export namespace ErpPurchaseReturnApi {
|
||||||
returnTime?: Date; // 退货时间
|
returnTime?: Date; // 退货时间
|
||||||
totalCount?: number; // 合计数量
|
totalCount?: number; // 合计数量
|
||||||
totalPrice: number; // 合计金额,单位:元
|
totalPrice: number; // 合计金额,单位:元
|
||||||
refundPrice?: number; // 已退款金额,单位:元
|
|
||||||
discountPercent?: number; // 折扣百分比
|
discountPercent?: number; // 折扣百分比
|
||||||
discountPrice?: number; // 折扣金额
|
discountPrice?: number; // 折扣金额
|
||||||
status?: number; // 状态
|
status?: number; // 状态
|
||||||
|
|
@ -25,7 +24,6 @@ export namespace ErpPurchaseReturnApi {
|
||||||
export interface PurchaseReturnItem {
|
export interface PurchaseReturnItem {
|
||||||
count?: number;
|
count?: number;
|
||||||
id?: number;
|
id?: number;
|
||||||
seq?: number; // 前端行号
|
|
||||||
orderItemId?: number;
|
orderItemId?: number;
|
||||||
productBarCode?: string;
|
productBarCode?: string;
|
||||||
productId?: number;
|
productId?: number;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ export namespace ErpSaleOrderApi {
|
||||||
/** 销售订单项 */
|
/** 销售订单项 */
|
||||||
export interface SaleOrderItem {
|
export interface SaleOrderItem {
|
||||||
id?: number; // 订单项编号
|
id?: number; // 订单项编号
|
||||||
seq?: number; // 前端行号
|
|
||||||
orderId?: number; // 采购订单编号
|
orderId?: number; // 采购订单编号
|
||||||
productId?: number; // 产品编号
|
productId?: number; // 产品编号
|
||||||
productName?: string; // 产品名称
|
productName?: string; // 产品名称
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ export namespace ErpSaleOutApi {
|
||||||
outTime?: Date; // 出库时间
|
outTime?: Date; // 出库时间
|
||||||
totalCount?: number; // 合计数量
|
totalCount?: number; // 合计数量
|
||||||
totalPrice?: number; // 合计金额,单位:元
|
totalPrice?: number; // 合计金额,单位:元
|
||||||
receiptPrice?: number; // 已收款金额,单位:元
|
|
||||||
status?: number; // 状态
|
status?: number; // 状态
|
||||||
remark?: string; // 备注
|
remark?: string; // 备注
|
||||||
discountPercent?: number; // 折扣百分比
|
discountPercent?: number; // 折扣百分比
|
||||||
|
|
@ -29,7 +28,6 @@ export namespace ErpSaleOutApi {
|
||||||
export interface SaleOutItem {
|
export interface SaleOutItem {
|
||||||
count?: number;
|
count?: number;
|
||||||
id?: number;
|
id?: number;
|
||||||
seq?: number; // 前端行号
|
|
||||||
orderItemId?: number;
|
orderItemId?: number;
|
||||||
productBarCode?: string;
|
productBarCode?: string;
|
||||||
productId?: number;
|
productId?: number;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ export namespace ErpSaleReturnApi {
|
||||||
returnTime?: Date; // 退货时间
|
returnTime?: Date; // 退货时间
|
||||||
totalCount?: number; // 合计数量
|
totalCount?: number; // 合计数量
|
||||||
totalPrice?: number; // 合计金额,单位:元
|
totalPrice?: number; // 合计金额,单位:元
|
||||||
refundPrice?: number; // 已退款金额,单位:元
|
|
||||||
status?: number; // 状态
|
status?: number; // 状态
|
||||||
remark?: string; // 备注
|
remark?: string; // 备注
|
||||||
discountPercent?: number; // 折扣百分比
|
discountPercent?: number; // 折扣百分比
|
||||||
|
|
@ -28,7 +27,6 @@ export namespace ErpSaleReturnApi {
|
||||||
export interface SaleReturnItem {
|
export interface SaleReturnItem {
|
||||||
count?: number;
|
count?: number;
|
||||||
id?: number;
|
id?: number;
|
||||||
seq?: number; // 前端行号
|
|
||||||
orderItemId?: number;
|
orderItemId?: number;
|
||||||
productBarCode?: string;
|
productBarCode?: string;
|
||||||
productId?: number;
|
productId?: number;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ export namespace ErpStockCheckApi {
|
||||||
/** 库存盘点项 */
|
/** 库存盘点项 */
|
||||||
export interface StockCheckItem {
|
export interface StockCheckItem {
|
||||||
id?: number; // 编号
|
id?: number; // 编号
|
||||||
seq?: number; // 前端行号
|
|
||||||
warehouseId?: number; // 仓库编号
|
warehouseId?: number; // 仓库编号
|
||||||
productId?: number; // 产品编号
|
productId?: number; // 产品编号
|
||||||
productName?: string; // 产品名称
|
productName?: string; // 产品名称
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,15 @@ export namespace ErpStockInApi {
|
||||||
/** 其它入库单产品信息 */
|
/** 其它入库单产品信息 */
|
||||||
export interface StockInItem {
|
export interface StockInItem {
|
||||||
id?: number; // 编号
|
id?: number; // 编号
|
||||||
seq?: number; // 前端行号
|
warehouseId: number; // 仓库编号
|
||||||
warehouseId?: number; // 仓库编号
|
productId: number; // 产品编号
|
||||||
productId?: number; // 产品编号
|
|
||||||
productName?: string; // 产品名称
|
productName?: string; // 产品名称
|
||||||
productUnitId?: number; // 产品单位编号
|
productUnitId?: number; // 产品单位编号
|
||||||
productUnitName?: string; // 产品单位名称
|
productUnitName?: string; // 产品单位名称
|
||||||
productBarCode?: string; // 产品条码
|
productBarCode?: string; // 产品条码
|
||||||
count?: number; // 数量
|
count: number; // 数量
|
||||||
productPrice?: number; // 产品单价
|
productPrice: number; // 产品单价
|
||||||
totalPrice?: number; // 总价
|
totalPrice: number; // 总价
|
||||||
stockCount?: number; // 库存数量
|
stockCount?: number; // 库存数量
|
||||||
remark?: string; // 备注
|
remark?: string; // 备注
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ export namespace ErpStockMoveApi {
|
||||||
count: number; // 数量
|
count: number; // 数量
|
||||||
fromWarehouseId?: number; // 来源仓库ID
|
fromWarehouseId?: number; // 来源仓库ID
|
||||||
id?: number; // ID
|
id?: number; // ID
|
||||||
seq?: number; // 前端行号
|
|
||||||
productBarCode: string; // 产品条形码
|
productBarCode: string; // 产品条形码
|
||||||
productId?: number; // 产品ID
|
productId?: number; // 产品ID
|
||||||
productName?: string; // 产品名称
|
productName?: string; // 产品名称
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ export namespace ErpStockOutApi {
|
||||||
/** 其它出库单产品信息 */
|
/** 其它出库单产品信息 */
|
||||||
export interface StockOutItem {
|
export interface StockOutItem {
|
||||||
id?: number; // 编号
|
id?: number; // 编号
|
||||||
seq?: number; // 前端行号
|
|
||||||
warehouseId?: number; // 仓库编号
|
warehouseId?: number; // 仓库编号
|
||||||
productId?: number; // 产品编号
|
productId?: number; // 产品编号
|
||||||
productName?: string; // 产品名称
|
productName?: string; // 产品名称
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImChannelMaterialApi {
|
|
||||||
/** 用户端能看到的频道素材详情 */
|
|
||||||
export interface Material {
|
|
||||||
id: number;
|
|
||||||
channelId: number;
|
|
||||||
type: number;
|
|
||||||
title: string;
|
|
||||||
coverUrl?: string;
|
|
||||||
summary?: string;
|
|
||||||
content?: string;
|
|
||||||
url?: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获取频道素材详情;用于客户端点击图文卡片渲染详情页 */
|
|
||||||
export function getChannelMaterial(id: number) {
|
|
||||||
return requestClient.get<ImChannelMaterialApi.Material>(
|
|
||||||
'/im/channel/material/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImConversationReadApi {
|
|
||||||
/** IM 会话读位置 Response VO */
|
|
||||||
export interface ConversationReadRespVO {
|
|
||||||
id: number; // 读位置编号(增量拉取游标用)
|
|
||||||
conversationType: number; // 会话类型,参见 ImConversationType
|
|
||||||
targetId: number; // 会话目标编号
|
|
||||||
messageId: number; // 最大已读消息编号
|
|
||||||
updateTime?: number; // 最近更新时间(毫秒时间戳,增量拉取游标用)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 增量拉取当前用户的会话读位置(重连 / 离线补偿) */
|
|
||||||
export function pullMyConversationReadList(params: {
|
|
||||||
lastId?: number;
|
|
||||||
lastUpdateTime?: number;
|
|
||||||
limit: number;
|
|
||||||
}) {
|
|
||||||
return requestClient.get<ImConversationReadApi.ConversationReadRespVO[]>(
|
|
||||||
'/im/conversation-read/pull',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImFacePackApi {
|
|
||||||
/** 用户端表情包项(精简版) */
|
|
||||||
export interface FacePackUserItem {
|
|
||||||
id: number;
|
|
||||||
url: string;
|
|
||||||
name?: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 用户端表情包 + 嵌套 items */
|
|
||||||
export interface FacePackUser {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
icon?: string;
|
|
||||||
items: FacePackUserItem[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 拉取所有启用的系统表情包(含表情列表) */
|
|
||||||
export function getFacePackList() {
|
|
||||||
return requestClient.get<ImFacePackApi.FacePackUser[]>('/im/face-pack/list');
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImFaceUserItemApi {
|
|
||||||
/** 个人表情 */
|
|
||||||
export interface FaceUserItem {
|
|
||||||
id: number;
|
|
||||||
url: string;
|
|
||||||
name?: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 添加个人表情请求 */
|
|
||||||
export interface FaceUserItemSaveReqVO {
|
|
||||||
url: string;
|
|
||||||
name?: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获取我的个人表情列表 */
|
|
||||||
export function getFaceUserItemList() {
|
|
||||||
return requestClient.get<ImFaceUserItemApi.FaceUserItem[]>('/im/face-user-item/list');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 添加个人表情 */
|
|
||||||
export function createFaceUserItem(data: ImFaceUserItemApi.FaceUserItemSaveReqVO) {
|
|
||||||
return requestClient.post<number>('/im/face-user-item/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除个人表情 */
|
|
||||||
export function deleteFaceUserItem(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/face-user-item/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImFriendApi {
|
|
||||||
/** IM 好友 Response VO */
|
|
||||||
export interface FriendRespVO {
|
|
||||||
id: number; // 关系记录编号
|
|
||||||
friendUserId: number; // 好友的用户编号
|
|
||||||
silent?: boolean; // 是否免打扰
|
|
||||||
displayName?: string; // 好友展示备注(仅自己可见)
|
|
||||||
displayNamePinyin?: string; // 备注的拼音(小写无空格,前端按首字母分桶 / 拼音搜索)
|
|
||||||
addSource?: number; // 添加来源;参见 ImFriendAddSourceEnum
|
|
||||||
pinned?: boolean; // 是否置顶联系人
|
|
||||||
blocked?: boolean; // 是否拉黑
|
|
||||||
status?: number; // 好友状态(0=正常,1=已删除)
|
|
||||||
addTime?: string; // 添加好友时间
|
|
||||||
deleteTime?: string; // 删除好友时间
|
|
||||||
updateTime?: number; // 最近更新时间(毫秒时间戳,增量拉取游标用)
|
|
||||||
nickname?: string; // 好友昵称
|
|
||||||
nicknamePinyin?: string; // 昵称的拼音(小写无空格,前端按首字母分桶 / 拼音搜索)
|
|
||||||
avatar?: string; // 好友头像
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IM 好友更新 Request VO */
|
|
||||||
export interface FriendUpdateReqVO {
|
|
||||||
friendUserId: number; // 好友的用户编号
|
|
||||||
silent?: boolean; // 是否免打扰
|
|
||||||
displayName?: string; // 好友展示备注
|
|
||||||
pinned?: boolean; // 是否置顶联系人
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得当前登录用户的好友列表 */
|
|
||||||
export function getMyFriendList() {
|
|
||||||
return requestClient.get<ImFriendApi.FriendRespVO[]>('/im/friend/list');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 增量拉取当前用户的好友关系(重连 / 离线补偿) */
|
|
||||||
export function pullMyFriendList(params: {
|
|
||||||
lastId?: number;
|
|
||||||
lastUpdateTime?: number;
|
|
||||||
limit: number;
|
|
||||||
}) {
|
|
||||||
return requestClient.get<ImFriendApi.FriendRespVO[]>('/im/friend/pull', { params });
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得好友详情 */
|
|
||||||
export function getFriend(friendUserId: number | string) {
|
|
||||||
return requestClient.get<ImFriendApi.FriendRespVO>('/im/friend/get', {
|
|
||||||
params: { friendUserId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除好友(单向软删除) */
|
|
||||||
export function deleteFriend(friendUserId: number | string, clear: boolean) {
|
|
||||||
return requestClient.delete<boolean>('/im/friend/delete', {
|
|
||||||
params: { friendUserId, clear },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 更新好友信息(备注 / 免打扰 / 联系人置顶) */
|
|
||||||
export function updateFriend(data: ImFriendApi.FriendUpdateReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/friend/update', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 拉黑好友(必须先是好友;单边屏蔽对方私聊消息) */
|
|
||||||
export function blockFriend(friendUserId: number | string) {
|
|
||||||
return requestClient.put<boolean>('/im/friend/block', undefined, {
|
|
||||||
params: { friendUserId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移出黑名单 */
|
|
||||||
export function unblockFriend(friendUserId: number | string) {
|
|
||||||
return requestClient.put<boolean>('/im/friend/unblock', undefined, {
|
|
||||||
params: { friendUserId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImFriendRequestApi {
|
|
||||||
/** IM 好友申请 Response VO */
|
|
||||||
export interface FriendRequestRespVO {
|
|
||||||
id: number; // 申请编号
|
|
||||||
fromUserId: number; // 发起方用户编号
|
|
||||||
toUserId: number; // 接收方用户编号
|
|
||||||
handleResult: number; // 处理结果;0=未处理;1=同意;2=拒绝
|
|
||||||
applyContent?: string; // 申请理由
|
|
||||||
handleContent?: string; // 处理理由(接收方拒绝时可选填)
|
|
||||||
addSource?: number; // 添加来源;参见 ImFriendAddSourceEnum
|
|
||||||
handleTime?: string; // 处理时间
|
|
||||||
createTime: string; // 申请创建时间
|
|
||||||
updateTime?: number; // 最近更新时间(毫秒时间戳,增量拉取游标用)
|
|
||||||
fromNickname?: string; // 发起方昵称
|
|
||||||
fromAvatar?: string; // 发起方头像
|
|
||||||
toNickname?: string; // 接收方昵称
|
|
||||||
toAvatar?: string; // 接收方头像
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IM 好友申请发起 Request VO */
|
|
||||||
export interface FriendRequestApplyReqVO {
|
|
||||||
toUserId: number; // 接收方用户编号
|
|
||||||
applyContent?: string; // 申请理由
|
|
||||||
displayName?: string; // 对接收方的备注(仅自己可见)
|
|
||||||
addSource?: number; // 添加来源
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 发起好友申请 */
|
|
||||||
export function applyFriendRequest(data: ImFriendRequestApi.FriendRequestApplyReqVO) {
|
|
||||||
return requestClient.post<null | number>('/im/friend-request/apply', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 同意好友申请 */
|
|
||||||
export function agreeFriendRequest(id: number | string) {
|
|
||||||
return requestClient.put<boolean>('/im/friend-request/agree', undefined, {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 拒绝好友申请 */
|
|
||||||
export function refuseFriendRequest(
|
|
||||||
id: number | string,
|
|
||||||
handleContent?: string,
|
|
||||||
) {
|
|
||||||
return requestClient.put<boolean>('/im/friend-request/refuse', undefined, {
|
|
||||||
params: { id, handleContent },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询「我相关」的好友申请列表(游标分页:传 maxId 加载更多) */
|
|
||||||
export function getMyFriendRequestList(limit: number, maxId?: number) {
|
|
||||||
const params: Record<string, number> = { limit };
|
|
||||||
if (maxId != null) {
|
|
||||||
params.maxId = maxId;
|
|
||||||
}
|
|
||||||
return requestClient.get<ImFriendRequestApi.FriendRequestRespVO[]>(
|
|
||||||
'/im/friend-request/list',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 增量拉取「我相关」的好友申请变更(重连 / 离线补偿) */
|
|
||||||
export function pullMyFriendRequestList(params: {
|
|
||||||
lastId?: number;
|
|
||||||
lastUpdateTime?: number;
|
|
||||||
limit: number;
|
|
||||||
}) {
|
|
||||||
return requestClient.get<ImFriendRequestApi.FriendRequestRespVO[]>(
|
|
||||||
'/im/friend-request/pull',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 按 id 单查「我相关」的申请记录(带越权过滤;WebSocket 通知到达后用) */
|
|
||||||
export function getMyFriendRequest(id: number) {
|
|
||||||
return requestClient.get<ImFriendRequestApi.FriendRequestRespVO | null>(
|
|
||||||
'/im/friend-request/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
import type { ImGroupMessageApi } from '#/api/im/message/group';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImGroupApi {
|
|
||||||
/** 群 Response VO */
|
|
||||||
export interface GroupRespVO {
|
|
||||||
id: number; // 编号
|
|
||||||
name: string; // 群名称
|
|
||||||
ownerUserId: number; // 群主用户编号
|
|
||||||
avatar?: string; // 群头像
|
|
||||||
notice?: string; // 群公告
|
|
||||||
banned?: boolean; // 是否封禁
|
|
||||||
mutedAll?: boolean; // 是否全群禁言
|
|
||||||
joinApproval?: boolean; // 进群是否需群主 / 管理员审批
|
|
||||||
bannedTime?: string; // 封禁时间
|
|
||||||
status: number; // 群状态(0=正常,1=已解散)
|
|
||||||
dissolvedTime?: string; // 解散时间
|
|
||||||
createTime?: string; // 创建时间
|
|
||||||
pinnedMessages?: ImGroupMessageApi.GroupMessageRespVO[]; // 群置顶消息列表(后端关联回填,仅当登录用户是群成员时非空)
|
|
||||||
joinStatus?: number; // 当前登录用户在该群的成员状态(参见 CommonStatusEnum:0 在群 / 1 已退群);历史退群群仍返回,供展示离线消息的群名 / 头像
|
|
||||||
groupRemark?: string; // 当前登录用户对该群的备注
|
|
||||||
silent?: boolean; // 当前登录用户是否免打扰
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群消息置顶 / 取消置顶 Request VO */
|
|
||||||
export interface GroupMessagePinReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
messageId: number; // 消息编号
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群创建 Request VO */
|
|
||||||
export interface GroupCreateReqVO {
|
|
||||||
name: string; // 群名称
|
|
||||||
memberUserIds?: number[]; // 初始成员用户编号列表(建群同时邀请的好友,不含创建者自己)
|
|
||||||
joinApproval?: boolean; // 进群是否需审批;不传默认 false 自由进群
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群更新 Request VO */
|
|
||||||
export interface GroupUpdateReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
name?: string; // 群名称
|
|
||||||
avatar?: string; // 群头像
|
|
||||||
notice?: string; // 群公告
|
|
||||||
joinApproval?: boolean; // 进群是否需审批
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 添加 / 撤销群管理员 Request VO */
|
|
||||||
export interface GroupAdminReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
userIds: number[]; // 目标用户编号列表
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群主转让 Request VO */
|
|
||||||
export interface GroupTransferOwnerReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
newOwnerUserId: number; // 新群主用户编号
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 全群禁言 / 取消 Request VO */
|
|
||||||
export interface GroupMuteAllReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
mutedAll: boolean; // 是否全群禁言
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 成员禁言 Request VO */
|
|
||||||
export interface GroupMuteMemberReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
userId: number; // 被禁言的用户编号
|
|
||||||
mutedSeconds: number; // 禁言时长(秒),0 表示永久禁言
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 取消成员禁言 Request VO */
|
|
||||||
export interface GroupCancelMuteMemberReqVO {
|
|
||||||
id: number; // 群编号
|
|
||||||
userId: number; // 被取消禁言的用户编号
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得当前登录用户的群列表 */
|
|
||||||
export function getMyGroupList() {
|
|
||||||
return requestClient.get<ImGroupApi.GroupRespVO[]>('/im/group/list');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得群详情 */
|
|
||||||
export function getGroup(id: number | string) {
|
|
||||||
return requestClient.get<ImGroupApi.GroupRespVO>('/im/group/get', { params: { id } });
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 创建群 */
|
|
||||||
export function createGroup(data: ImGroupApi.GroupCreateReqVO) {
|
|
||||||
return requestClient.post<ImGroupApi.GroupRespVO>('/im/group/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 更新群 */
|
|
||||||
export function updateGroup(data: ImGroupApi.GroupUpdateReqVO) {
|
|
||||||
return requestClient.put<ImGroupApi.GroupRespVO>('/im/group/update', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 解散群 */
|
|
||||||
export function dissolveGroup(id: number | string) {
|
|
||||||
return requestClient.delete<boolean>('/im/group/dissolve', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 添加群管理员(仅群主可调) */
|
|
||||||
export function addGroupAdmin(data: ImGroupApi.GroupAdminReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/add-admin', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 撤销群管理员(仅群主可调) */
|
|
||||||
export function removeGroupAdmin(data: ImGroupApi.GroupAdminReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/remove-admin', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 转让群主(仅老群主可调;旧群主转让后降为普通成员) */
|
|
||||||
export function transferGroupOwner(data: ImGroupApi.GroupTransferOwnerReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/transfer-owner', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 置顶群消息(仅群主 / 管理员可调) */
|
|
||||||
export function pinGroupMessage(data: ImGroupApi.GroupMessagePinReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/pin-message', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 取消置顶群消息(仅群主 / 管理员可调) */
|
|
||||||
export function unpinGroupMessage(data: ImGroupApi.GroupMessagePinReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/unpin-message', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 全群禁言 / 取消(仅群主 / 管理员可调) */
|
|
||||||
export function muteAll(data: ImGroupApi.GroupMuteAllReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/mute-all', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 禁言成员 */
|
|
||||||
export function muteMember(data: ImGroupApi.GroupMuteMemberReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/mute-member', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 取消成员禁言 */
|
|
||||||
export function cancelMuteMember(data: ImGroupApi.GroupCancelMuteMemberReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group/cancel-mute-member', data);
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImGroupMemberApi {
|
|
||||||
/** 群成员 Response VO */
|
|
||||||
export interface GroupMemberRespVO {
|
|
||||||
id: number; // 编号
|
|
||||||
groupId: number; // 群编号
|
|
||||||
userId: number; // 用户编号
|
|
||||||
displayUserName?: string; // 组内显示名(群主设置的备注)
|
|
||||||
groupRemark?: string; // 群备注(当前用户对群的备注)
|
|
||||||
silent?: boolean; // 是否免打扰
|
|
||||||
status?: number; // 成员状态(0=在群,1=退群)
|
|
||||||
role?: number; // 成员角色,参见 ImGroupMemberRole 枚举
|
|
||||||
joinTime?: string; // 入群时间
|
|
||||||
quitTime?: string; // 退群时间
|
|
||||||
muteEndTime?: string; // 禁言到期时间
|
|
||||||
createTime?: string; // 创建时间
|
|
||||||
nickname?: string; // 用户昵称
|
|
||||||
avatar?: string; // 用户头像
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群成员邀请 Request VO */
|
|
||||||
export interface GroupMemberInviteReqVO {
|
|
||||||
groupId: number; // 群编号
|
|
||||||
memberUserIds: number[]; // 被邀请的用户编号列表
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群成员移除 Request VO */
|
|
||||||
export interface GroupMemberRemoveReqVO {
|
|
||||||
groupId: number; // 群编号
|
|
||||||
memberUserIds: number[]; // 被移除的用户编号列表
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群成员更新 Request VO */
|
|
||||||
export interface GroupMemberUpdateReqVO {
|
|
||||||
groupId: number; // 群编号
|
|
||||||
displayUserName?: string; // 群内昵称
|
|
||||||
groupRemark?: string; // 群备注
|
|
||||||
silent?: boolean; // 是否免打扰
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 邀请用户加入群 */
|
|
||||||
export function inviteGroupMember(data: ImGroupMemberApi.GroupMemberInviteReqVO) {
|
|
||||||
return requestClient.post<boolean>('/im/group/invite', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 退出群 */
|
|
||||||
export function quitGroup(groupId: number | string) {
|
|
||||||
return requestClient.delete<boolean>('/im/group/quit', {
|
|
||||||
params: { groupId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移除群成员 */
|
|
||||||
export function removeGroupMember(data: ImGroupMemberApi.GroupMemberRemoveReqVO) {
|
|
||||||
return requestClient.delete<boolean>('/im/group/kicking', { data });
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得群成员详情 */
|
|
||||||
export function getGroupMember(groupId: number, userId: number) {
|
|
||||||
return requestClient.get<ImGroupMemberApi.GroupMemberRespVO>('/im/group-member/get', {
|
|
||||||
params: { groupId, userId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得指定群的成员列表(聚合 AdminUser 昵称 / 头像) */
|
|
||||||
export function getGroupMemberList(groupId: number | string) {
|
|
||||||
return requestClient.get<ImGroupMemberApi.GroupMemberRespVO[]>('/im/group-member/list', {
|
|
||||||
params: { groupId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 更新群成员 */
|
|
||||||
export function updateGroupMember(data: ImGroupMemberApi.GroupMemberUpdateReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/group-member/update', data);
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImGroupRequestApi {
|
|
||||||
/** IM 加群申请 Response VO */
|
|
||||||
export interface GroupRequestRespVO {
|
|
||||||
id: number; // 申请编号
|
|
||||||
groupId: number; // 群编号
|
|
||||||
userId: number; // 申请人 / 被邀请人用户编号
|
|
||||||
inviterUserId?: number; // 邀请人;NULL 表示用户主动申请
|
|
||||||
handleResult: number; // 处理结果;0=未处理;1=同意;2=拒绝
|
|
||||||
applyContent?: string; // 申请理由
|
|
||||||
handleContent?: string; // 处理理由(拒绝时可选填)
|
|
||||||
handleUserId?: number; // 处理人用户编号
|
|
||||||
addSource?: number; // 加入来源;参见 ImGroupAddSourceEnum
|
|
||||||
handleTime?: string; // 处理时间
|
|
||||||
createTime: string; // 申请创建时间
|
|
||||||
updateTime?: number; // 最近更新时间(毫秒时间戳,增量拉取游标用)
|
|
||||||
userNickname?: string; // 申请人 / 被邀请人昵称
|
|
||||||
userAvatar?: string; // 申请人 / 被邀请人头像
|
|
||||||
inviterNickname?: string; // 邀请人昵称
|
|
||||||
inviterAvatar?: string; // 邀请人头像
|
|
||||||
groupName?: string; // 群名称
|
|
||||||
groupAvatar?: string; // 群头像
|
|
||||||
}
|
|
||||||
|
|
||||||
/** IM 加群申请发起 Request VO */
|
|
||||||
export interface GroupRequestApplyReqVO {
|
|
||||||
groupId: number; // 群编号
|
|
||||||
applyContent?: string; // 申请理由
|
|
||||||
addSource?: number; // 加入来源
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 申请加群 */
|
|
||||||
export function applyJoinGroup(data: ImGroupRequestApi.GroupRequestApplyReqVO) {
|
|
||||||
return requestClient.post<null | number>('/im/group-request/apply', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 同意加群申请(群主或管理员) */
|
|
||||||
export function agreeGroupRequest(id: number | string) {
|
|
||||||
return requestClient.put<boolean>('/im/group-request/agree', undefined, {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 拒绝加群申请(群主或管理员) */
|
|
||||||
export function refuseGroupRequest(
|
|
||||||
id: number | string,
|
|
||||||
handleContent?: string,
|
|
||||||
) {
|
|
||||||
return requestClient.put<boolean>('/im/group-request/refuse', undefined, {
|
|
||||||
params: { id, handleContent },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询「我管理的所有群」下的未处理加群申请列表(不分页);前端 store 据此派生横幅红点 + Drawer 列表 */
|
|
||||||
export function getUnhandledRequestList() {
|
|
||||||
return requestClient.get<ImGroupRequestApi.GroupRequestRespVO[]>(
|
|
||||||
'/im/group-request/unhandled-list',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询指定群下的全部加群申请(含已处理);仅群主 / 管理员可查 */
|
|
||||||
export function getGroupRequestListByGroupId(groupId: number) {
|
|
||||||
return requestClient.get<ImGroupRequestApi.GroupRequestRespVO[]>(
|
|
||||||
'/im/group-request/list-by-group',
|
|
||||||
{ params: { groupId } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 按 id 单查申请记录(带越权过滤;WebSocket 通知到达后用) */
|
|
||||||
export function getMyGroupRequest(id: number) {
|
|
||||||
return requestClient.get<ImGroupRequestApi.GroupRequestRespVO | null>(
|
|
||||||
'/im/group-request/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 增量拉取我管理的所有群下加群申请变更(重连 / 离线补偿) */
|
|
||||||
export function pullMyGroupRequestList(params: {
|
|
||||||
lastId?: number;
|
|
||||||
lastUpdateTime?: number;
|
|
||||||
limit: number;
|
|
||||||
}) {
|
|
||||||
return requestClient.get<ImGroupRequestApi.GroupRequestRespVO[]>(
|
|
||||||
'/im/group-request/pull',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerChannelApi {
|
|
||||||
/** 频道 */
|
|
||||||
export interface Channel {
|
|
||||||
id: number;
|
|
||||||
code: string;
|
|
||||||
name: string;
|
|
||||||
avatar?: string;
|
|
||||||
sort: number;
|
|
||||||
status: number;
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得频道分页 */
|
|
||||||
export function getManagerChannelPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerChannelApi.Channel>>(
|
|
||||||
'/im/manager/channel/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得频道详情 */
|
|
||||||
export function getManagerChannel(id: number) {
|
|
||||||
return requestClient.get<ImManagerChannelApi.Channel>('/im/manager/channel/get', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增频道 */
|
|
||||||
export function createManagerChannel(data: ImManagerChannelApi.Channel) {
|
|
||||||
return requestClient.post<number>('/im/manager/channel/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改频道 */
|
|
||||||
export function updateManagerChannel(data: ImManagerChannelApi.Channel) {
|
|
||||||
return requestClient.put<boolean>('/im/manager/channel/update', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除频道 */
|
|
||||||
export function deleteManagerChannel(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/channel/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得启用的频道精简列表(表单选择用) */
|
|
||||||
export function getSimpleChannelList() {
|
|
||||||
return requestClient.get<ImManagerChannelApi.Channel[]>(
|
|
||||||
'/im/manager/channel/simple-list',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerChannelMaterialApi {
|
|
||||||
/** 频道素材 */
|
|
||||||
export interface Material {
|
|
||||||
id: number;
|
|
||||||
channelId: number;
|
|
||||||
channelName?: string;
|
|
||||||
type: number;
|
|
||||||
title: string;
|
|
||||||
coverUrl?: string;
|
|
||||||
summary?: string;
|
|
||||||
content?: string;
|
|
||||||
url?: string;
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得素材分页 */
|
|
||||||
export function getManagerChannelMaterialPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerChannelMaterialApi.Material>>(
|
|
||||||
'/im/manager/channel-material/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得指定频道下的素材精简列表 */
|
|
||||||
export function getSimpleManagerChannelMaterialList(channelId: number) {
|
|
||||||
return requestClient.get<ImManagerChannelMaterialApi.Material[]>(
|
|
||||||
'/im/manager/channel-material/simple-list',
|
|
||||||
{ params: { channelId } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得素材详情 */
|
|
||||||
export function getManagerChannelMaterial(id: number) {
|
|
||||||
return requestClient.get<ImManagerChannelMaterialApi.Material>(
|
|
||||||
'/im/manager/channel-material/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增素材 */
|
|
||||||
export function createManagerChannelMaterial(
|
|
||||||
data: ImManagerChannelMaterialApi.Material,
|
|
||||||
) {
|
|
||||||
return requestClient.post<number>('/im/manager/channel-material/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改素材 */
|
|
||||||
export function updateManagerChannelMaterial(
|
|
||||||
data: ImManagerChannelMaterialApi.Material,
|
|
||||||
) {
|
|
||||||
return requestClient.put<boolean>(
|
|
||||||
'/im/manager/channel-material/update',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除素材 */
|
|
||||||
export function deleteManagerChannelMaterial(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/channel-material/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerChannelMessageApi {
|
|
||||||
/** 频道消息 */
|
|
||||||
export interface ChannelMessage {
|
|
||||||
id: number;
|
|
||||||
channelId: number;
|
|
||||||
channelName?: string;
|
|
||||||
materialId: number;
|
|
||||||
materialTitle?: string;
|
|
||||||
materialCoverUrl?: string;
|
|
||||||
type: number;
|
|
||||||
content?: string;
|
|
||||||
receiverUserIds?: number[];
|
|
||||||
sendTime?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 频道消息发送请求 */
|
|
||||||
export interface ChannelMessageSendReqVO {
|
|
||||||
materialId: number;
|
|
||||||
receiverUserIds?: number[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 立即推送频道消息 */
|
|
||||||
export function sendManagerChannelMessage(
|
|
||||||
data: ImManagerChannelMessageApi.ChannelMessageSendReqVO,
|
|
||||||
) {
|
|
||||||
return requestClient.post<number>('/im/manager/channel-message/send', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除频道消息 */
|
|
||||||
export function deleteManagerChannelMessage(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/channel-message/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得频道消息分页 */
|
|
||||||
export function getManagerChannelMessagePage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerChannelMessageApi.ChannelMessage>>(
|
|
||||||
'/im/manager/channel-message/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerFacePackItemApi {
|
|
||||||
/** 表情项 */
|
|
||||||
export interface FacePackItem {
|
|
||||||
id: number;
|
|
||||||
packId: number;
|
|
||||||
url: string;
|
|
||||||
name?: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
sort: number;
|
|
||||||
status: number;
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得表情分页 */
|
|
||||||
export function getManagerFacePackItemPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerFacePackItemApi.FacePackItem>>(
|
|
||||||
'/im/manager/face-pack-item/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得表情详情 */
|
|
||||||
export function getManagerFacePackItem(id: number) {
|
|
||||||
return requestClient.get<ImManagerFacePackItemApi.FacePackItem>(
|
|
||||||
'/im/manager/face-pack-item/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增表情 */
|
|
||||||
export function createManagerFacePackItem(data: ImManagerFacePackItemApi.FacePackItem) {
|
|
||||||
return requestClient.post<number>('/im/manager/face-pack-item/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改表情 */
|
|
||||||
export function updateManagerFacePackItem(data: ImManagerFacePackItemApi.FacePackItem) {
|
|
||||||
return requestClient.put<boolean>(
|
|
||||||
'/im/manager/face-pack-item/update',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除表情 */
|
|
||||||
export function deleteManagerFacePackItem(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/face-pack-item/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 批量删除表情 */
|
|
||||||
export function deleteManagerFacePackItemList(ids: number[]) {
|
|
||||||
return requestClient.delete<boolean>(
|
|
||||||
'/im/manager/face-pack-item/delete-list',
|
|
||||||
{ params: { ids: ids.join(',') } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerFacePackApi {
|
|
||||||
/** 表情包 */
|
|
||||||
export interface FacePack {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
icon?: string;
|
|
||||||
sort: number;
|
|
||||||
status: number;
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得表情包分页 */
|
|
||||||
export function getManagerFacePackPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerFacePackApi.FacePack>>(
|
|
||||||
'/im/manager/face-pack/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得表情包详情 */
|
|
||||||
export function getManagerFacePack(id: number) {
|
|
||||||
return requestClient.get<ImManagerFacePackApi.FacePack>('/im/manager/face-pack/get', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增表情包 */
|
|
||||||
export function createManagerFacePack(data: ImManagerFacePackApi.FacePack) {
|
|
||||||
return requestClient.post<number>('/im/manager/face-pack/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改表情包 */
|
|
||||||
export function updateManagerFacePack(data: ImManagerFacePackApi.FacePack) {
|
|
||||||
return requestClient.put<boolean>('/im/manager/face-pack/update', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除表情包 */
|
|
||||||
export function deleteManagerFacePack(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/face-pack/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 批量删除表情包 */
|
|
||||||
export function deleteManagerFacePackList(ids: number[]) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/face-pack/delete-list', {
|
|
||||||
params: { ids: ids.join(',') },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerFaceUserItemApi {
|
|
||||||
/** 用户表情 */
|
|
||||||
export interface FaceUserItem {
|
|
||||||
id: number;
|
|
||||||
userId: number;
|
|
||||||
userNickname?: string;
|
|
||||||
url: string;
|
|
||||||
name?: string;
|
|
||||||
width?: number;
|
|
||||||
height?: number;
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得用户表情分页 */
|
|
||||||
export function getManagerFaceUserItemPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerFaceUserItemApi.FaceUserItem>>(
|
|
||||||
'/im/manager/face-user-item/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除用户表情 */
|
|
||||||
export function deleteManagerFaceUserItem(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/face-user-item/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerFriendApi {
|
|
||||||
/** 好友关系 */
|
|
||||||
export interface Friend {
|
|
||||||
id: number;
|
|
||||||
userId: number;
|
|
||||||
userNickname?: string;
|
|
||||||
friendUserId: number;
|
|
||||||
friendNickname?: string;
|
|
||||||
displayName?: string;
|
|
||||||
addSource?: number;
|
|
||||||
silent: boolean;
|
|
||||||
pinned: boolean;
|
|
||||||
blocked: boolean;
|
|
||||||
status: number;
|
|
||||||
addTime?: Date;
|
|
||||||
deleteTime?: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得好友关系分页 */
|
|
||||||
export function getManagerFriendPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerFriendApi.Friend>>(
|
|
||||||
'/im/manager/friend/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerFriendRequestApi {
|
|
||||||
/** 好友申请 */
|
|
||||||
export interface FriendRequest {
|
|
||||||
id: number;
|
|
||||||
fromUserId: number;
|
|
||||||
fromNickname?: string;
|
|
||||||
toUserId: number;
|
|
||||||
toNickname?: string;
|
|
||||||
applyContent?: string;
|
|
||||||
displayName?: string;
|
|
||||||
addSource?: number;
|
|
||||||
handleResult: number;
|
|
||||||
handleContent?: string;
|
|
||||||
handleTime?: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得好友申请分页 */
|
|
||||||
export function getManagerFriendRequestPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerFriendRequestApi.FriendRequest>>(
|
|
||||||
'/im/manager/friend-request/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerGroupApi {
|
|
||||||
/** 群 */
|
|
||||||
export interface Group {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
avatar?: string;
|
|
||||||
notice?: string;
|
|
||||||
ownerUserId: number;
|
|
||||||
ownerNickname?: string;
|
|
||||||
memberCount?: number;
|
|
||||||
status: number;
|
|
||||||
banned: boolean;
|
|
||||||
mutedAll?: boolean; // 是否全群禁言
|
|
||||||
bannedReason?: string;
|
|
||||||
bannedTime?: Date;
|
|
||||||
dissolvedTime?: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群成员 */
|
|
||||||
export interface GroupMember {
|
|
||||||
userId: number;
|
|
||||||
nickname?: string;
|
|
||||||
avatar?: string;
|
|
||||||
displayUserName?: string;
|
|
||||||
groupRemark?: string;
|
|
||||||
silent?: boolean;
|
|
||||||
status: number;
|
|
||||||
role?: number; // 成员角色,参见 ImGroupMemberRole 枚举
|
|
||||||
joinTime?: Date;
|
|
||||||
quitTime?: Date;
|
|
||||||
muteEndTime?: Date; // 禁言到期时间
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群封禁请求 */
|
|
||||||
export interface GroupBanReqVO {
|
|
||||||
id: number;
|
|
||||||
reason: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得群分页 */
|
|
||||||
export function getManagerGroupPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerGroupApi.Group>>(
|
|
||||||
'/im/manager/group/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得群详情 */
|
|
||||||
export function getManagerGroup(id: number) {
|
|
||||||
return requestClient.get<ImManagerGroupApi.Group>('/im/manager/group/get', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 封禁群 */
|
|
||||||
export function banManagerGroup(data: ImManagerGroupApi.GroupBanReqVO) {
|
|
||||||
return requestClient.put<boolean>('/im/manager/group/ban', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 解封群 */
|
|
||||||
export function unbanManagerGroup(id: number) {
|
|
||||||
return requestClient.put<boolean>('/im/manager/group/unban', undefined, {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 解散群 */
|
|
||||||
export function dissolveManagerGroup(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/group/dissolve', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得群成员列表(含已退群成员,由前端按需过滤) */
|
|
||||||
export function getManagerGroupMemberList(groupId: number) {
|
|
||||||
return requestClient.get<ImManagerGroupApi.GroupMember[]>(
|
|
||||||
'/im/manager/group/member/list',
|
|
||||||
{ params: { groupId } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerGroupRequestApi {
|
|
||||||
/** 加群申请 */
|
|
||||||
export interface GroupRequest {
|
|
||||||
id: number;
|
|
||||||
groupId: number;
|
|
||||||
groupName?: string;
|
|
||||||
userId: number;
|
|
||||||
userNickname?: string;
|
|
||||||
inviterUserId?: number;
|
|
||||||
inviterNickname?: string;
|
|
||||||
applyContent?: string;
|
|
||||||
addSource?: number;
|
|
||||||
handleResult: number;
|
|
||||||
handleUserId?: number;
|
|
||||||
handleNickname?: string;
|
|
||||||
handleContent?: string;
|
|
||||||
handleTime?: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得加群申请分页 */
|
|
||||||
export function getManagerGroupRequestPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerGroupRequestApi.GroupRequest>>(
|
|
||||||
'/im/manager/group-request/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerGroupMessageApi {
|
|
||||||
/** 群聊消息 */
|
|
||||||
export interface GroupMessage {
|
|
||||||
id: number;
|
|
||||||
clientMessageId?: string;
|
|
||||||
groupId: number;
|
|
||||||
groupName?: string;
|
|
||||||
senderId: number;
|
|
||||||
senderNickname?: string;
|
|
||||||
type: number;
|
|
||||||
content: string;
|
|
||||||
status: number;
|
|
||||||
atUserIds?: number[];
|
|
||||||
atUserNicknames?: (null | string)[];
|
|
||||||
receiptStatus: number;
|
|
||||||
sendTime: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得群聊消息分页 */
|
|
||||||
export function getManagerGroupMessagePage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerGroupMessageApi.GroupMessage>>(
|
|
||||||
'/im/manager/message/group/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得群聊消息详情 */
|
|
||||||
export function getManagerGroupMessage(id: number) {
|
|
||||||
return requestClient.get<ImManagerGroupMessageApi.GroupMessage>(
|
|
||||||
'/im/manager/message/group/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerPrivateMessageApi {
|
|
||||||
/** 私聊消息 */
|
|
||||||
export interface PrivateMessage {
|
|
||||||
id: number;
|
|
||||||
clientMessageId?: string;
|
|
||||||
senderId: number;
|
|
||||||
senderNickname?: string;
|
|
||||||
receiverId: number;
|
|
||||||
receiverNickname?: string;
|
|
||||||
type: number;
|
|
||||||
content: string;
|
|
||||||
status: number;
|
|
||||||
receiptStatus?: number;
|
|
||||||
sendTime: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得私聊消息分页 */
|
|
||||||
export function getManagerPrivateMessagePage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerPrivateMessageApi.PrivateMessage>>(
|
|
||||||
'/im/manager/message/private/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得私聊消息详情 */
|
|
||||||
export function getManagerPrivateMessage(id: number) {
|
|
||||||
return requestClient.get<ImManagerPrivateMessageApi.PrivateMessage>(
|
|
||||||
'/im/manager/message/private/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerRtcApi {
|
|
||||||
/** RTC 通话 */
|
|
||||||
export interface RtcCall {
|
|
||||||
id: number;
|
|
||||||
room: string;
|
|
||||||
conversationType: number;
|
|
||||||
mediaType: number;
|
|
||||||
inviterUserId: number;
|
|
||||||
inviterNickname?: string;
|
|
||||||
groupId?: number;
|
|
||||||
groupName?: string;
|
|
||||||
status: number;
|
|
||||||
endReason?: number;
|
|
||||||
startTime: Date;
|
|
||||||
acceptTime?: Date;
|
|
||||||
endTime?: Date;
|
|
||||||
createTime: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** RTC 通话参与者 */
|
|
||||||
export interface RtcParticipant {
|
|
||||||
id: number;
|
|
||||||
callId: number;
|
|
||||||
userId: number;
|
|
||||||
userNickname?: string;
|
|
||||||
role: number;
|
|
||||||
status: number;
|
|
||||||
inviteTime: Date;
|
|
||||||
acceptTime?: Date;
|
|
||||||
leaveTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得通话记录分页 */
|
|
||||||
export function getManagerRtcCallPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerRtcApi.RtcCall>>(
|
|
||||||
'/im/manager/rtc/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得通话参与者列表 */
|
|
||||||
export function getManagerRtcCallParticipantList(id: number) {
|
|
||||||
return requestClient.get<ImManagerRtcApi.RtcParticipant[]>(
|
|
||||||
'/im/manager/rtc/participant-list',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerSensitiveWordApi {
|
|
||||||
/** 敏感词 */
|
|
||||||
export interface SensitiveWord {
|
|
||||||
id: number;
|
|
||||||
word: string;
|
|
||||||
status: number;
|
|
||||||
creator?: string;
|
|
||||||
creatorName?: string;
|
|
||||||
createTime?: Date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得敏感词分页 */
|
|
||||||
export function getManagerSensitiveWordPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<ImManagerSensitiveWordApi.SensitiveWord>>(
|
|
||||||
'/im/manager/sensitive-word/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得敏感词详情 */
|
|
||||||
export function getManagerSensitiveWord(id: number) {
|
|
||||||
return requestClient.get<ImManagerSensitiveWordApi.SensitiveWord>(
|
|
||||||
'/im/manager/sensitive-word/get',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 新增敏感词 */
|
|
||||||
export function createManagerSensitiveWord(data: ImManagerSensitiveWordApi.SensitiveWord) {
|
|
||||||
return requestClient.post<number>('/im/manager/sensitive-word/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 修改敏感词 */
|
|
||||||
export function updateManagerSensitiveWord(data: ImManagerSensitiveWordApi.SensitiveWord) {
|
|
||||||
return requestClient.put<boolean>(
|
|
||||||
'/im/manager/sensitive-word/update',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除敏感词 */
|
|
||||||
export function deleteManagerSensitiveWord(id: number) {
|
|
||||||
return requestClient.delete<boolean>('/im/manager/sensitive-word/delete', {
|
|
||||||
params: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 批量删除敏感词 */
|
|
||||||
export function deleteManagerSensitiveWordList(ids: number[]) {
|
|
||||||
return requestClient.delete<boolean>(
|
|
||||||
'/im/manager/sensitive-word/delete-list',
|
|
||||||
{ params: { ids: ids.join(',') } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImManagerStatisticsApi {
|
|
||||||
/** 统计概览 */
|
|
||||||
export interface Overview {
|
|
||||||
totalUser: number;
|
|
||||||
newUserToday: number;
|
|
||||||
totalGroup: number;
|
|
||||||
newGroupToday: number;
|
|
||||||
activeUserDaily: number;
|
|
||||||
activeUserWeekly: number;
|
|
||||||
activeUserMonthly: number;
|
|
||||||
privateMessageToday: number;
|
|
||||||
groupMessageToday: number;
|
|
||||||
privateMessageYesterday: number;
|
|
||||||
groupMessageYesterday: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 趋势数据 */
|
|
||||||
export interface Trend {
|
|
||||||
dates: string[];
|
|
||||||
series: Record<string, number[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 消息类型分布 */
|
|
||||||
export interface MessageType {
|
|
||||||
type: number; // 参见 ImContentTypeEnum 枚举类,由前端按 DICT_TYPE.IM_CONTENT_TYPE 翻译
|
|
||||||
value: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群规模分布 */
|
|
||||||
export interface GroupSize {
|
|
||||||
range: string;
|
|
||||||
count: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 消息发送排行 */
|
|
||||||
export interface TopSender {
|
|
||||||
userId: number;
|
|
||||||
nickname: string;
|
|
||||||
messageCount: number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 获得 KPI 概览 */
|
|
||||||
export function getStatisticsOverview() {
|
|
||||||
return requestClient.get<ImManagerStatisticsApi.Overview>(
|
|
||||||
'/im/manager/statistics/overview',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得消息趋势(私聊 + 群聊双线) */
|
|
||||||
export function getMessageTrend(days: number) {
|
|
||||||
return requestClient.get<ImManagerStatisticsApi.Trend>(
|
|
||||||
'/im/manager/statistics/message-trend',
|
|
||||||
{ params: { days } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得用户趋势(新增注册 + 日活双线) */
|
|
||||||
export function getUserTrend(days: number) {
|
|
||||||
return requestClient.get<ImManagerStatisticsApi.Trend>(
|
|
||||||
'/im/manager/statistics/user-trend',
|
|
||||||
{ params: { days } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得内容类型分布(最近 30 天) */
|
|
||||||
export function getMessageTypeDistribution() {
|
|
||||||
return requestClient.get<ImManagerStatisticsApi.MessageType[]>(
|
|
||||||
'/im/manager/statistics/message-type-distribution',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得群规模分布 */
|
|
||||||
export function getGroupSizeDistribution() {
|
|
||||||
return requestClient.get<ImManagerStatisticsApi.GroupSize[]>(
|
|
||||||
'/im/manager/statistics/group-size-distribution',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获得消息 TOP 发送者(最近 30 天) */
|
|
||||||
export function getTopSenders() {
|
|
||||||
return requestClient.get<ImManagerStatisticsApi.TopSender[]>(
|
|
||||||
'/im/manager/statistics/top-senders',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImChannelMessageApi {
|
|
||||||
/** 频道消息 */
|
|
||||||
export interface ChannelMessageRespVO {
|
|
||||||
id: number;
|
|
||||||
clientMessageId?: string;
|
|
||||||
channelId: number;
|
|
||||||
materialId: number;
|
|
||||||
type: number;
|
|
||||||
content: string;
|
|
||||||
receiptStatus?: number;
|
|
||||||
sendTime: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 拉取当前用户应收的频道消息(离线增量);按 minId 游标分页 */
|
|
||||||
export function pullChannelMessageList(
|
|
||||||
params: { minId: number; size?: number },
|
|
||||||
signal?: AbortSignal,
|
|
||||||
) {
|
|
||||||
return requestClient.get<ImChannelMessageApi.ChannelMessageRespVO[]>(
|
|
||||||
'/im/channel/message/pull',
|
|
||||||
{ params, signal },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 上报频道消息已读位置;切到频道会话或拉到新消息后调 */
|
|
||||||
export function readChannelMessages(channelId: number, messageId: number) {
|
|
||||||
return requestClient.put<boolean>('/im/channel/message/read', undefined, {
|
|
||||||
params: { channelId, messageId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImGroupMessageApi {
|
|
||||||
/** 群聊消息 Response VO */
|
|
||||||
export interface GroupMessageRespVO {
|
|
||||||
id: number; // 消息编号
|
|
||||||
clientMessageId: string; // 客户端消息编号
|
|
||||||
senderId: number; // 发送人编号
|
|
||||||
groupId: number; // 群编号
|
|
||||||
type: number; // 内容类型
|
|
||||||
content: string; // 消息内容(JSON 格式)
|
|
||||||
status: number; // 消息状态
|
|
||||||
sendTime: string; // 发送时间
|
|
||||||
atUserIds?: number[]; // @ 目标用户编号列表
|
|
||||||
receiverUserIds?: number[]; // 定向接收用户编号列表
|
|
||||||
receiptStatus?: number; // 回执状态
|
|
||||||
readCount?: number; // 已读人数(回执消息、且发送人为当前用户时有值)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群聊消息发送 Request VO */
|
|
||||||
export interface GroupMessageSendReqVO {
|
|
||||||
clientMessageId: string; // 客户端消息编号
|
|
||||||
groupId: number; // 群编号
|
|
||||||
type: number; // 内容类型
|
|
||||||
content: string; // 消息内容(JSON 格式)
|
|
||||||
atUserIds?: number[]; // @ 目标用户编号列表
|
|
||||||
receipt?: boolean; // 是否需要回执
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群聊历史消息列表 Request VO */
|
|
||||||
export interface GroupMessageListReqVO {
|
|
||||||
groupId: number | string; // 群编号
|
|
||||||
maxId?: number | string; // 起始消息编号(不含),为空则从最新消息开始
|
|
||||||
limit: number; // 拉取数量(1 ~ 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 发送群聊消息 */
|
|
||||||
export function sendGroupMessage(data: ImGroupMessageApi.GroupMessageSendReqVO) {
|
|
||||||
return requestClient.post<ImGroupMessageApi.GroupMessageRespVO>(
|
|
||||||
'/im/message/group/send',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 拉取群聊消息(增量) */
|
|
||||||
export function pullGroupMessageList(
|
|
||||||
params: { minId: number | string; size: number },
|
|
||||||
signal?: AbortSignal,
|
|
||||||
) {
|
|
||||||
return requestClient.get<ImGroupMessageApi.GroupMessageRespVO[]>(
|
|
||||||
'/im/message/group/pull',
|
|
||||||
{ params, signal },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询群聊历史消息 */
|
|
||||||
export function getGroupMessageList(params: ImGroupMessageApi.GroupMessageListReqVO) {
|
|
||||||
return requestClient.get<ImGroupMessageApi.GroupMessageRespVO[]>(
|
|
||||||
'/im/message/group/list',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 标记群聊消息已读 */
|
|
||||||
export function readGroupMessages(
|
|
||||||
groupId: number | string,
|
|
||||||
messageId: number | string,
|
|
||||||
) {
|
|
||||||
return requestClient.put<boolean>('/im/message/group/read', undefined, {
|
|
||||||
params: { groupId, messageId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 撤回群聊消息 */
|
|
||||||
export function recallGroupMessage(id: number | string) {
|
|
||||||
return requestClient.delete<ImGroupMessageApi.GroupMessageRespVO>(
|
|
||||||
'/im/message/group/recall',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取群消息已读用户列表 */
|
|
||||||
export function getGroupReadUsers(params: {
|
|
||||||
groupId: number | string;
|
|
||||||
messageId: number | string;
|
|
||||||
}) {
|
|
||||||
return requestClient.get<number[]>('/im/message/group/get-read-user-ids', {
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImPrivateMessageApi {
|
|
||||||
/** 私聊消息 Response VO */
|
|
||||||
export interface PrivateMessageRespVO {
|
|
||||||
id: number; // 消息编号
|
|
||||||
clientMessageId: string; // 客户端消息编号
|
|
||||||
senderId: number; // 发送人编号
|
|
||||||
receiverId: number; // 接收人编号
|
|
||||||
type: number; // 内容类型
|
|
||||||
content: string; // 消息内容(JSON 格式)
|
|
||||||
status: number; // 消息状态(正常 / 已撤回)
|
|
||||||
receiptStatus?: number; // 回执状态(不需要 / 待完成 / 已完成),对齐 ImMessageReceiptStatus
|
|
||||||
sendTime: string; // 发送时间
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 私聊消息发送 Request VO */
|
|
||||||
export interface PrivateMessageSendReqVO {
|
|
||||||
clientMessageId: string; // 客户端消息编号
|
|
||||||
receiverId: number; // 接收人编号
|
|
||||||
type: number; // 内容类型
|
|
||||||
content: string; // 消息内容(JSON 格式)
|
|
||||||
receipt?: boolean; // 是否需要回执;不传后端默认 true(普通私聊用户消息)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 私聊历史消息列表 Request VO */
|
|
||||||
export interface PrivateMessageListReqVO {
|
|
||||||
receiverId: number | string; // 接收人编号(对方)
|
|
||||||
maxId?: number | string; // 起始消息编号(不含),为空则从最新消息开始
|
|
||||||
limit: number; // 拉取数量(1 ~ 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 发送私聊消息 */
|
|
||||||
export function sendPrivateMessage(data: ImPrivateMessageApi.PrivateMessageSendReqVO) {
|
|
||||||
return requestClient.post<ImPrivateMessageApi.PrivateMessageRespVO>(
|
|
||||||
'/im/message/private/send',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 拉取私聊消息(增量) */
|
|
||||||
export function pullPrivateMessageList(
|
|
||||||
params: { minId: number | string; size: number },
|
|
||||||
signal?: AbortSignal,
|
|
||||||
) {
|
|
||||||
return requestClient.get<ImPrivateMessageApi.PrivateMessageRespVO[]>(
|
|
||||||
'/im/message/private/pull',
|
|
||||||
{ params, signal },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询私聊历史消息 */
|
|
||||||
export function getPrivateMessageList(params: ImPrivateMessageApi.PrivateMessageListReqVO) {
|
|
||||||
return requestClient.get<ImPrivateMessageApi.PrivateMessageRespVO[]>(
|
|
||||||
'/im/message/private/list',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 标记私聊消息已读 */
|
|
||||||
export function readPrivateMessages(
|
|
||||||
receiverId: number | string,
|
|
||||||
messageId: number | string,
|
|
||||||
) {
|
|
||||||
return requestClient.put<boolean>('/im/message/private/read', undefined, {
|
|
||||||
params: { receiverId, messageId },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询对方已读到我发的最大消息 id(多端 / 离线后用于补齐已读状态) */
|
|
||||||
export function getPrivateMaxReadMessageId(
|
|
||||||
peerId: number | string,
|
|
||||||
signal?: AbortSignal,
|
|
||||||
) {
|
|
||||||
return requestClient.get<null | number>(
|
|
||||||
'/im/message/private/max-read-message-id',
|
|
||||||
{ params: { peerId }, signal },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 撤回私聊消息 */
|
|
||||||
export function recallPrivateMessage(id: number | string) {
|
|
||||||
return requestClient.delete<ImPrivateMessageApi.PrivateMessageRespVO>(
|
|
||||||
'/im/message/private/recall',
|
|
||||||
{ params: { id } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace ImRtcApi {
|
|
||||||
/** 创建新通话请求 VO */
|
|
||||||
export interface RtcCallCreateReqVO {
|
|
||||||
conversationType: number;
|
|
||||||
mediaType: number;
|
|
||||||
groupId?: number;
|
|
||||||
inviteeIds: number[]; // 被邀请的用户编号集合;私聊必传 1 个对端,群聊必传至少 1 人
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 通话中追加邀请请求 VO;仅群通话可用 */
|
|
||||||
export interface RtcCallInviteReqVO {
|
|
||||||
room: string;
|
|
||||||
inviteeIds: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 通话会话 VO;create / join / accept / refreshToken 共用 */
|
|
||||||
export interface RtcCallRespVO {
|
|
||||||
room: string; // 业务通话编号(同时作为 LiveKit 房间名)
|
|
||||||
livekitUrl: string;
|
|
||||||
token?: string; // ENDED 状态时为 null(无需 connect LiveKit)
|
|
||||||
conversationType: number;
|
|
||||||
mediaType: number;
|
|
||||||
status: number;
|
|
||||||
endReason?: number; // 结束原因;仅 status=ENDED 时有值
|
|
||||||
inviterId: number;
|
|
||||||
groupId?: number;
|
|
||||||
inviteeIds?: number[];
|
|
||||||
joinedUserIds?: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 群活跃通话查询响应;不含 token */
|
|
||||||
export interface RtcGroupCallRespVO {
|
|
||||||
room: string;
|
|
||||||
groupId: number;
|
|
||||||
mediaType: number;
|
|
||||||
inviterId: number;
|
|
||||||
joinedUserIds?: number[];
|
|
||||||
inviteeIds?: number[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 创建新通话;私聊或群聊根据 conversationType 区分 */
|
|
||||||
export function createCall(data: ImRtcApi.RtcCallCreateReqVO) {
|
|
||||||
return requestClient.post<ImRtcApi.RtcCallRespVO>('/im/rtc/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 通话中追加邀请;仅群通话可用 */
|
|
||||||
export function inviteCall(data: ImRtcApi.RtcCallInviteReqVO) {
|
|
||||||
return requestClient.post<boolean>('/im/rtc/invite', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 加入已有群通话;用于胶囊条「加入」按钮 */
|
|
||||||
export function joinCall(room: string) {
|
|
||||||
return requestClient.post<ImRtcApi.RtcCallRespVO>('/im/rtc/join', undefined, {
|
|
||||||
params: { room },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 接听通话 */
|
|
||||||
export function acceptCall(room: string) {
|
|
||||||
return requestClient.post<ImRtcApi.RtcCallRespVO>('/im/rtc/accept', undefined, {
|
|
||||||
params: { room },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 拒绝通话 */
|
|
||||||
export function rejectCall(room: string) {
|
|
||||||
return requestClient.post<boolean>('/im/rtc/reject', undefined, {
|
|
||||||
params: { room },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 取消邀请;主叫接通前调用 */
|
|
||||||
export function cancelCall(room: string) {
|
|
||||||
return requestClient.post<boolean>('/im/rtc/cancel', undefined, {
|
|
||||||
params: { room },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 离开通话;接通后调用 */
|
|
||||||
export function leaveCall(room: string) {
|
|
||||||
return requestClient.post<boolean>('/im/rtc/leave', undefined, {
|
|
||||||
params: { room },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 振铃超时检查;RUNNING 端 timer 兜底,触发后端立即扫描该 room 的超时 INVITING(接口静默) */
|
|
||||||
export function noAnswerCallCheck(room: string) {
|
|
||||||
return requestClient.post<boolean>(
|
|
||||||
'/im/rtc/no-answer-call-check',
|
|
||||||
undefined,
|
|
||||||
{ params: { room } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 查询当前进行中的通话;目前仅群聊场景(胶囊条),返回 null 表示无活跃通话 */
|
|
||||||
export function getActiveCall(groupId: number) {
|
|
||||||
return requestClient.get<ImRtcApi.RtcGroupCallRespVO | null>(
|
|
||||||
'/im/rtc/get-active-call',
|
|
||||||
{ params: { groupId } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -24,18 +24,6 @@ export namespace InfraCodegenApi {
|
||||||
parentMenuId: number;
|
parentMenuId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 代码生成表保存请求 */
|
|
||||||
export interface CodegenTableSaveReqVO extends CodegenTable {
|
|
||||||
frontType?: null | number;
|
|
||||||
genPath?: string;
|
|
||||||
genType?: string;
|
|
||||||
masterTableId?: number;
|
|
||||||
subJoinColumnId?: number;
|
|
||||||
subJoinMany?: boolean;
|
|
||||||
treeParentColumnId?: number;
|
|
||||||
treeNameColumnId?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 代码生成字段定义 */
|
/** 代码生成字段定义 */
|
||||||
export interface CodegenColumn {
|
export interface CodegenColumn {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -66,7 +54,7 @@ export namespace InfraCodegenApi {
|
||||||
|
|
||||||
/** 代码生成详情 */
|
/** 代码生成详情 */
|
||||||
export interface CodegenDetail {
|
export interface CodegenDetail {
|
||||||
table: CodegenTableSaveReqVO;
|
table: CodegenTable;
|
||||||
columns: CodegenColumn[];
|
columns: CodegenColumn[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,7 +66,7 @@ export namespace InfraCodegenApi {
|
||||||
|
|
||||||
/** 更新代码生成请求 */
|
/** 更新代码生成请求 */
|
||||||
export interface CodegenUpdateReqVO {
|
export interface CodegenUpdateReqVO {
|
||||||
table: CodegenTableSaveReqVO;
|
table: any | CodegenTable;
|
||||||
columns: CodegenColumn[];
|
columns: CodegenColumn[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export namespace Demo02CategoryApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询示例分类列表 */
|
/** 查询示例分类列表 */
|
||||||
export function getDemo02CategoryList(params?: any) {
|
export function getDemo02CategoryList(params: any) {
|
||||||
return requestClient.get<Demo02CategoryApi.Demo02Category[]>(
|
return requestClient.get<Demo02CategoryApi.Demo02Category[]>(
|
||||||
'/infra/demo02-category/list',
|
'/infra/demo02-category/list',
|
||||||
{ params },
|
{ params },
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
@ -5,7 +7,7 @@ import { requestClient } from '#/api/request';
|
||||||
export namespace Demo03StudentApi {
|
export namespace Demo03StudentApi {
|
||||||
/** 学生课程信息 */
|
/** 学生课程信息 */
|
||||||
export interface Demo03Course {
|
export interface Demo03Course {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
studentId?: number; // 学生编号
|
studentId?: number; // 学生编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
score?: number; // 分数
|
score?: number; // 分数
|
||||||
|
|
@ -13,7 +15,7 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 学生班级信息 */
|
/** 学生班级信息 */
|
||||||
export interface Demo03Grade {
|
export interface Demo03Grade {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
studentId?: number; // 学生编号
|
studentId?: number; // 学生编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
teacher?: string; // 班主任
|
teacher?: string; // 班主任
|
||||||
|
|
@ -21,10 +23,10 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 学生信息 */
|
/** 学生信息 */
|
||||||
export interface Demo03Student {
|
export interface Demo03Student {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
sex?: number; // 性别
|
sex?: number; // 性别
|
||||||
birthday?: number | string; // 出生日期
|
birthday?: Dayjs | string; // 出生日期
|
||||||
description?: string; // 简介
|
description?: string; // 简介
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
@ -5,7 +7,7 @@ import { requestClient } from '#/api/request';
|
||||||
export namespace Demo03StudentApi {
|
export namespace Demo03StudentApi {
|
||||||
/** 学生课程信息 */
|
/** 学生课程信息 */
|
||||||
export interface Demo03Course {
|
export interface Demo03Course {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
studentId?: number; // 学生编号
|
studentId?: number; // 学生编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
score?: number; // 分数
|
score?: number; // 分数
|
||||||
|
|
@ -13,7 +15,7 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 学生班级信息 */
|
/** 学生班级信息 */
|
||||||
export interface Demo03Grade {
|
export interface Demo03Grade {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
studentId?: number; // 学生编号
|
studentId?: number; // 学生编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
teacher?: string; // 班主任
|
teacher?: string; // 班主任
|
||||||
|
|
@ -21,10 +23,10 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 学生信息 */
|
/** 学生信息 */
|
||||||
export interface Demo03Student {
|
export interface Demo03Student {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
sex?: number; // 性别
|
sex?: number; // 性别
|
||||||
birthday?: number | string; // 出生日期
|
birthday?: Dayjs | string; // 出生日期
|
||||||
description?: string; // 简介
|
description?: string; // 简介
|
||||||
demo03courses?: Demo03Course[];
|
demo03courses?: Demo03Course[];
|
||||||
demo03grade?: Demo03Grade;
|
demo03grade?: Demo03Grade;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
import type { PageParam, PageResult } from '@vben/request';
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
@ -5,7 +7,7 @@ import { requestClient } from '#/api/request';
|
||||||
export namespace Demo03StudentApi {
|
export namespace Demo03StudentApi {
|
||||||
/** 学生课程信息 */
|
/** 学生课程信息 */
|
||||||
export interface Demo03Course {
|
export interface Demo03Course {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
studentId?: number; // 学生编号
|
studentId?: number; // 学生编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
score?: number; // 分数
|
score?: number; // 分数
|
||||||
|
|
@ -13,7 +15,7 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 学生班级信息 */
|
/** 学生班级信息 */
|
||||||
export interface Demo03Grade {
|
export interface Demo03Grade {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
studentId?: number; // 学生编号
|
studentId?: number; // 学生编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
teacher?: string; // 班主任
|
teacher?: string; // 班主任
|
||||||
|
|
@ -21,10 +23,10 @@ export namespace Demo03StudentApi {
|
||||||
|
|
||||||
/** 学生信息 */
|
/** 学生信息 */
|
||||||
export interface Demo03Student {
|
export interface Demo03Student {
|
||||||
id?: number; // 编号
|
id: number; // 编号
|
||||||
name?: string; // 名字
|
name?: string; // 名字
|
||||||
sex?: number; // 性别
|
sex?: number; // 性别
|
||||||
birthday?: number | string; // 出生日期
|
birthday?: Dayjs | string; // 出生日期
|
||||||
description?: string; // 简介
|
description?: string; // 简介
|
||||||
demo03courses?: Demo03Course[];
|
demo03courses?: Demo03Course[];
|
||||||
demo03grade?: Demo03Grade;
|
demo03grade?: Demo03Grade;
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,3 @@ export function runJob(id: number) {
|
||||||
export function getJobNextTimes(id: number) {
|
export function getJobNextTimes(id: number) {
|
||||||
return requestClient.get(`/infra/job/get_next_times?id=${id}`);
|
return requestClient.get(`/infra/job/get_next_times?id=${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 同步定时任务到 Quartz */
|
|
||||||
export function syncJob() {
|
|
||||||
return requestClient.post('/infra/job/sync');
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,37 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace AlertConfigApi {
|
export namespace AlertConfigApi {
|
||||||
/** IoT 告警配置 */
|
/** IoT 告警配置 VO */
|
||||||
export interface AlertConfig {
|
export interface AlertConfig {
|
||||||
id?: number;
|
id?: number;
|
||||||
name?: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
level?: number;
|
level?: number;
|
||||||
status?: number;
|
status?: number;
|
||||||
sceneRuleIds?: number[];
|
sceneRuleIds?: number[];
|
||||||
receiveUserIds?: number[];
|
receiveUserIds?: number[];
|
||||||
receiveUserNames?: string[];
|
receiveUserNames?: string;
|
||||||
receiveTypes?: number[];
|
receiveTypes?: number[];
|
||||||
smsTemplateCode?: string;
|
|
||||||
mailTemplateCode?: string;
|
|
||||||
notifyTemplateCode?: string;
|
|
||||||
createTime?: Date;
|
createTime?: Date;
|
||||||
|
updateTime?: Date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** IoT 告警配置 */
|
||||||
|
export interface AlertConfig {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
description?: string;
|
||||||
|
level?: number;
|
||||||
|
status?: number;
|
||||||
|
sceneRuleIds?: number[];
|
||||||
|
receiveUserIds?: number[];
|
||||||
|
receiveUserNames?: string;
|
||||||
|
receiveTypes?: number[];
|
||||||
|
createTime?: Date;
|
||||||
|
updateTime?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
/** 查询告警配置分页 */
|
/** 查询告警配置分页 */
|
||||||
export function getAlertConfigPage(params: PageParam) {
|
export function getAlertConfigPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<AlertConfigApi.AlertConfig>>(
|
return requestClient.get<PageResult<AlertConfigApi.AlertConfig>>(
|
||||||
|
|
@ -36,20 +49,20 @@ export function getAlertConfig(id: number) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取告警配置简单列表 */
|
/** 查询所有告警配置列表 */
|
||||||
export function getSimpleAlertConfigList() {
|
export function getAlertConfigList() {
|
||||||
return requestClient.get<AlertConfigApi.AlertConfig[]>(
|
return requestClient.get<AlertConfigApi.AlertConfig[]>(
|
||||||
'/iot/alert-config/simple-list',
|
'/iot/alert-config/list',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增告警配置 */
|
/** 新增告警配置 */
|
||||||
export function createAlertConfig(data: AlertConfigApi.AlertConfig) {
|
export function createAlertConfig(data: AlertConfig) {
|
||||||
return requestClient.post('/iot/alert-config/create', data);
|
return requestClient.post('/iot/alert-config/create', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 修改告警配置 */
|
/** 修改告警配置 */
|
||||||
export function updateAlertConfig(data: AlertConfigApi.AlertConfig) {
|
export function updateAlertConfig(data: AlertConfig) {
|
||||||
return requestClient.put('/iot/alert-config/update', data);
|
return requestClient.put('/iot/alert-config/update', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,3 +70,25 @@ export function updateAlertConfig(data: AlertConfigApi.AlertConfig) {
|
||||||
export function deleteAlertConfig(id: number) {
|
export function deleteAlertConfig(id: number) {
|
||||||
return requestClient.delete(`/iot/alert-config/delete?id=${id}`);
|
return requestClient.delete(`/iot/alert-config/delete?id=${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量删除告警配置 */
|
||||||
|
export function deleteAlertConfigList(ids: number[]) {
|
||||||
|
return requestClient.delete('/iot/alert-config/delete-list', {
|
||||||
|
params: { ids: ids.join(',') },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 启用/禁用告警配置 */
|
||||||
|
export function toggleAlertConfig(id: number, enabled: boolean) {
|
||||||
|
return requestClient.put(`/iot/alert-config/toggle`, {
|
||||||
|
id,
|
||||||
|
enabled,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取告警配置简单列表 */
|
||||||
|
export function getSimpleAlertConfigList() {
|
||||||
|
return requestClient.get<AlertConfigApi.AlertConfig[]>(
|
||||||
|
'/iot/alert-config/simple-list',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,41 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace AlertRecordApi {
|
export namespace AlertRecordApi {
|
||||||
/** IoT 告警记录 */
|
/** IoT 告警记录 VO */
|
||||||
export interface AlertRecord {
|
export interface AlertRecord {
|
||||||
id?: number;
|
id?: number;
|
||||||
configId?: number;
|
configId?: number;
|
||||||
configName?: string;
|
configName?: string;
|
||||||
configLevel?: number;
|
configLevel?: number;
|
||||||
deviceId?: number;
|
deviceId?: number;
|
||||||
|
deviceName?: string;
|
||||||
productId?: number;
|
productId?: number;
|
||||||
deviceMessage?: any;
|
productName?: string;
|
||||||
|
deviceMessage?: string;
|
||||||
processStatus?: boolean;
|
processStatus?: boolean;
|
||||||
processRemark?: string;
|
processRemark?: string;
|
||||||
|
processTime?: Date;
|
||||||
createTime?: Date;
|
createTime?: Date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** IoT 告警记录 */
|
||||||
|
export interface AlertRecord {
|
||||||
|
id?: number;
|
||||||
|
configId?: number;
|
||||||
|
configName?: string;
|
||||||
|
configLevel?: number;
|
||||||
|
deviceId?: number;
|
||||||
|
deviceName?: string;
|
||||||
|
productId?: number;
|
||||||
|
productName?: string;
|
||||||
|
deviceMessage?: string;
|
||||||
|
processStatus?: boolean;
|
||||||
|
processRemark?: string;
|
||||||
|
processTime?: Date;
|
||||||
|
createTime?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
/** 查询告警记录分页 */
|
/** 查询告警记录分页 */
|
||||||
export function getAlertRecordPage(params: PageParam) {
|
export function getAlertRecordPage(params: PageParam) {
|
||||||
return requestClient.get<PageResult<AlertRecordApi.AlertRecord>>(
|
return requestClient.get<PageResult<AlertRecordApi.AlertRecord>>(
|
||||||
|
|
@ -34,9 +54,29 @@ export function getAlertRecord(id: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 处理告警记录 */
|
/** 处理告警记录 */
|
||||||
export function processAlertRecord(id: number, processRemark?: string) {
|
export function processAlertRecord(id: number, remark?: string) {
|
||||||
return requestClient.put('/iot/alert-record/process', {
|
return requestClient.put('/iot/alert-record/process', {
|
||||||
id,
|
id,
|
||||||
processRemark,
|
remark,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量处理告警记录 */
|
||||||
|
export function batchProcessAlertRecord(ids: number[], remark?: string) {
|
||||||
|
return requestClient.put('/iot/alert-record/batch-process', {
|
||||||
|
ids,
|
||||||
|
remark,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除告警记录 */
|
||||||
|
export function deleteAlertRecord(id: number) {
|
||||||
|
return requestClient.delete(`/iot/alert-record/delete?id=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除告警记录 */
|
||||||
|
export function deleteAlertRecordList(ids: number[]) {
|
||||||
|
return requestClient.delete('/iot/alert-record/delete-list', {
|
||||||
|
params: { ids: ids.join(',') },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,8 +150,11 @@ export function importDeviceTemplate() {
|
||||||
/** 导入设备 */
|
/** 导入设备 */
|
||||||
export function importDevice(file: File, updateSupport: boolean) {
|
export function importDevice(file: File, updateSupport: boolean) {
|
||||||
return requestClient.upload<IotDeviceApi.DeviceImportRespVO>(
|
return requestClient.upload<IotDeviceApi.DeviceImportRespVO>(
|
||||||
`/iot/device/import?updateSupport=${updateSupport}`,
|
'/iot/device/import',
|
||||||
{ file },
|
{
|
||||||
|
file,
|
||||||
|
updateSupport,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,7 +168,7 @@ export function getLatestDeviceProperties(params: any) {
|
||||||
|
|
||||||
/** 获取设备属性历史数据 */
|
/** 获取设备属性历史数据 */
|
||||||
export function getHistoryDevicePropertyList(params: any) {
|
export function getHistoryDevicePropertyList(params: any) {
|
||||||
return requestClient.get<IotDeviceApi.DeviceProperty[]>(
|
return requestClient.get<PageResult<IotDeviceApi.DeviceProperty>>(
|
||||||
'/iot/device/property/history-list',
|
'/iot/device/property/history-list',
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace IotDeviceModbusConfigApi {
|
|
||||||
/** Modbus 连接配置 VO */
|
|
||||||
export interface ModbusConfig {
|
|
||||||
id?: number; // 主键
|
|
||||||
deviceId: number; // 设备编号
|
|
||||||
ip: string; // Modbus 服务器 IP 地址
|
|
||||||
port: number; // Modbus 服务器端口
|
|
||||||
slaveId: number; // 从站地址
|
|
||||||
timeout: number; // 连接超时时间,单位:毫秒
|
|
||||||
retryInterval: number; // 重试间隔,单位:毫秒
|
|
||||||
mode: number; // 模式
|
|
||||||
frameFormat: number; // 帧格式
|
|
||||||
status: number; // 状态
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取设备的 Modbus 连接配置 */
|
|
||||||
export function getModbusConfig(deviceId: number) {
|
|
||||||
return requestClient.get<IotDeviceModbusConfigApi.ModbusConfig>(
|
|
||||||
'/iot/device-modbus-config/get',
|
|
||||||
{ params: { deviceId } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 保存 Modbus 连接配置 */
|
|
||||||
export function saveModbusConfig(data: IotDeviceModbusConfigApi.ModbusConfig) {
|
|
||||||
return requestClient.post('/iot/device-modbus-config/save', data);
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
import type { PageParam, PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
|
||||||
|
|
||||||
export namespace IotDeviceModbusPointApi {
|
|
||||||
/** Modbus 点位配置 VO */
|
|
||||||
export interface ModbusPoint {
|
|
||||||
id?: number; // 主键
|
|
||||||
deviceId: number; // 设备编号
|
|
||||||
thingModelId?: number; // 物模型属性编号
|
|
||||||
identifier: string; // 属性标识符
|
|
||||||
name: string; // 属性名称
|
|
||||||
functionCode?: number; // Modbus 功能码
|
|
||||||
registerAddress?: number; // 寄存器起始地址
|
|
||||||
registerCount?: number; // 寄存器数量
|
|
||||||
byteOrder?: string; // 字节序
|
|
||||||
rawDataType?: string; // 原始数据类型
|
|
||||||
scale: number; // 缩放因子
|
|
||||||
pollInterval: number; // 轮询间隔,单位:毫秒
|
|
||||||
status: number; // 状态
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取设备的 Modbus 点位分页 */
|
|
||||||
export function getModbusPointPage(params: PageParam) {
|
|
||||||
return requestClient.get<PageResult<IotDeviceModbusPointApi.ModbusPoint>>(
|
|
||||||
'/iot/device-modbus-point/page',
|
|
||||||
{ params },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 获取 Modbus 点位详情 */
|
|
||||||
export function getModbusPoint(id: number) {
|
|
||||||
return requestClient.get<IotDeviceModbusPointApi.ModbusPoint>(
|
|
||||||
`/iot/device-modbus-point/get?id=${id}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 创建 Modbus 点位配置 */
|
|
||||||
export function createModbusPoint(data: IotDeviceModbusPointApi.ModbusPoint) {
|
|
||||||
return requestClient.post('/iot/device-modbus-point/create', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 更新 Modbus 点位配置 */
|
|
||||||
export function updateModbusPoint(data: IotDeviceModbusPointApi.ModbusPoint) {
|
|
||||||
return requestClient.put('/iot/device-modbus-point/update', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 删除 Modbus 点位配置 */
|
|
||||||
export function deleteModbusPoint(id: number) {
|
|
||||||
return requestClient.delete(`/iot/device-modbus-point/delete?id=${id}`);
|
|
||||||
}
|
|
||||||