feat: first commit
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
# dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
dist
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// Generated by 'unplugin-auto-import'
|
||||||
|
// We suggest you to commit this file into source control
|
||||||
|
declare global {
|
||||||
|
|
||||||
|
}
|
||||||
|
export {}
|
||||||
Vendored
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// generated by unplugin-vue-components
|
||||||
|
// We suggest you to commit this file into source control
|
||||||
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
Angle: typeof import('./src/components/Angle.vue')['default']
|
||||||
|
Autoresponsive: typeof import('./src/components/autoresponsive.vue')['default']
|
||||||
|
CalcRectDock: typeof import('./src/components/CalcRectDock.vue')['default']
|
||||||
|
CodeMirror: typeof import('./src/components/CodeMirror.vue')['default']
|
||||||
|
CountDownMessage: typeof import('./src/components/CountDownMessage.vue')['default']
|
||||||
|
DynamicTags: typeof import('./src/components/DynamicTags.vue')['default']
|
||||||
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
|
ElLink: typeof import('element-plus/es')['ElLink']
|
||||||
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
|
ImgPreview: typeof import('./src/components/ImgPreview.vue')['default']
|
||||||
|
Layout: typeof import('./src/components/Layout.vue')['default']
|
||||||
|
ObjectRect: typeof import('./src/components/ObjectRect.vue')['default']
|
||||||
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
SingleUpload: typeof import('./src/components/SingleUpload.vue')['default']
|
||||||
|
SystemLayout: typeof import('./src/components/SystemLayout.vue')['default']
|
||||||
|
SystemMenu: typeof import('./src/components/SystemMenu.vue')['default']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {}
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,161 @@
|
|||||||
|
这段代码是一个使用装饰器实现的Vue表格组件配置类,主要用于管理系统中的通知(Notice)数据的增删改查操作。以下是对代码的详细分析:
|
||||||
|
|
||||||
|
### 1. 核心功能
|
||||||
|
- **数据展示**:通过装饰器配置表格列和搜索表单
|
||||||
|
- **CRUD操作**:实现通知的创建、读取、更新、删除功能
|
||||||
|
- **表单验证**:内置字段验证规则
|
||||||
|
- **权限控制**:支持动态显示操作按钮
|
||||||
|
- **API集成**:与后端接口对接
|
||||||
|
|
||||||
|
### 2. 主要装饰器解析
|
||||||
|
|
||||||
|
#### 2.1 字段装饰器
|
||||||
|
```typescript
|
||||||
|
@tcpd({ "lang": "", "def": "消息", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "消息", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
message: string = ""
|
||||||
|
```
|
||||||
|
- `@tcpd`:配置表格列属性
|
||||||
|
- minWidth:最小列宽
|
||||||
|
- def:列显示名称
|
||||||
|
- `@tfcpd`:配置表单字段属性
|
||||||
|
- fieldType:字段类型
|
||||||
|
- rule:验证规则
|
||||||
|
|
||||||
|
#### 2.2 方法装饰器
|
||||||
|
```typescript
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar",
|
||||||
|
"value": {
|
||||||
|
"type": "添加",
|
||||||
|
"priority": 1,
|
||||||
|
"es": "onAfter",
|
||||||
|
"dialogContent": UmTableForm,
|
||||||
|
"dialogTitle": "增加",
|
||||||
|
"dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => { ... }
|
||||||
|
```
|
||||||
|
- `@tcmd`:配置表格操作
|
||||||
|
- type:操作类型(添加/编辑/删除)
|
||||||
|
- dialogContent:使用的表单组件
|
||||||
|
- dialogWidth:对话框宽度
|
||||||
|
- sort:操作按钮排序
|
||||||
|
|
||||||
|
### 3. 核心方法说明
|
||||||
|
|
||||||
|
#### 3.1 数据获取
|
||||||
|
```typescript
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getNoticeList(params);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 通过API获取通知列表
|
||||||
|
- 装饰器配置为搜索表单的后置方法
|
||||||
|
|
||||||
|
#### 3.2 新增操作
|
||||||
|
```typescript
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addNotice({ ...data, userId: Notice.userId });
|
||||||
|
return { code: code === 0 ? 0 : 1, message: msg };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 提交新增请求
|
||||||
|
- 自动附加用户ID
|
||||||
|
- 返回操作结果
|
||||||
|
|
||||||
|
#### 3.3 编辑操作
|
||||||
|
```typescript
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", ... } })
|
||||||
|
getDetail = async (rowId: number) => {
|
||||||
|
const { data } = await api.getNotice({ id: rowId });
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onAfter", ... } })
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateNotice({ ...params, userId: Notice.userId });
|
||||||
|
return { code: code === 0 ? 0 : 1, message: msg };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 分两个阶段处理:
|
||||||
|
1. getDetail:编辑前获取详情数据
|
||||||
|
2. onEdit:提交编辑请求
|
||||||
|
|
||||||
|
#### 3.4 删除操作
|
||||||
|
```typescript
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del",
|
||||||
|
"es": "onAfter",
|
||||||
|
"dialogContent": "确定要删除该条数据吗?"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteNotice({ ids: [rowId] });
|
||||||
|
return { code: code === 0 ? 0 : 1, message: msg };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 删除前弹出确认对话框
|
||||||
|
- 支持批量删除(当前实现为单条删除)
|
||||||
|
|
||||||
|
### 4. 特色功能实现
|
||||||
|
|
||||||
|
#### 4.1 动态显示控制
|
||||||
|
```typescript
|
||||||
|
isShow = (rowData: any) => {
|
||||||
|
return rowData?.source_add_type == "1";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- 通过判断数据字段决定是否显示操作按钮
|
||||||
|
|
||||||
|
#### 4.2 用户上下文
|
||||||
|
```typescript
|
||||||
|
static userId: any;
|
||||||
|
```
|
||||||
|
- 通过静态属性存储当前用户ID
|
||||||
|
- 在提交操作时自动附加到请求参数
|
||||||
|
|
||||||
|
### 5. 使用建议
|
||||||
|
|
||||||
|
1. **用户ID设置**:
|
||||||
|
```typescript
|
||||||
|
// 在使用前设置当前用户ID
|
||||||
|
Notice.userId = store.getters.userId;
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **自定义操作扩展**:
|
||||||
|
```typescript
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"id": 1,
|
||||||
|
"type": "customOperateEvent",
|
||||||
|
"title": "详情",
|
||||||
|
isShow: (row) => row.status === 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
customAction = (rowId: number) => {
|
||||||
|
router.push(`/detail/${rowId}`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **表单验证增强**:
|
||||||
|
```typescript
|
||||||
|
@tfcpd({
|
||||||
|
fieldType: "number",
|
||||||
|
rule: [
|
||||||
|
{ type: "require", message: "不能为空" },
|
||||||
|
{ validator: (v) => v > 0, message: "必须大于0" }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
sort: number = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **国际化支持**:
|
||||||
|
```typescript
|
||||||
|
@tcpd({ lang: "notice.message", def: "消息" })
|
||||||
|
```
|
||||||
|
|
||||||
|
该设计通过装饰器实现了高度可配置的表格组件,建议结合具体业务需求扩展装饰器配置,并确保API接口的异常处理完备。
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>‎</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "funjia-table-viewmodel-template",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite --port=4444",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview --port=4444"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/lang-javascript": "^6.1.7",
|
||||||
|
"@kousum/vue3-window": "^0.0.3",
|
||||||
|
"@types/axios": "^0.14.0",
|
||||||
|
"@types/js-cookie": "^3.0.1",
|
||||||
|
"autoresponsive-vue3": "^2.0.4",
|
||||||
|
"axios": "^0.26.1",
|
||||||
|
"codemirror": "^6.0.1",
|
||||||
|
"dayjs": "^1.10.7",
|
||||||
|
"element-plus": "2.1.10",
|
||||||
|
"funjialib": "git+http://git.funjia.top/funjia/FunJiaLib_Package.git",
|
||||||
|
"funjiaui": "git+http://git.funjia.top/funjia/FunjiaUI_Vue.git#v1.1.2",
|
||||||
|
"funjia-axios": "git+http://git.funjia.top/funjia/funjia-axios.git",
|
||||||
|
"html-print-element": "^0.0.5",
|
||||||
|
"html2pdf.js": "^0.10.2",
|
||||||
|
"js-cookie": "^3.0.1",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"md5": "^2.3.0",
|
||||||
|
"pinia": "2.0.13",
|
||||||
|
"printd": "^1.6.0",
|
||||||
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
|
"vue": "3.2.33",
|
||||||
|
"vue-codemirror": "^6.1.1",
|
||||||
|
"vue-cropperjs": "^5.0.0",
|
||||||
|
"vue-router": "^4.0.14",
|
||||||
|
"vue3-dnd": "^2.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/lodash-es": "^4.17.6",
|
||||||
|
"@types/node": "^17.0.25",
|
||||||
|
"@vitejs/plugin-vue": "^2.3.1",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"sass": "^1.50.1",
|
||||||
|
"typescript": "^4.5.4",
|
||||||
|
"unplugin-auto-import": "^0.7.1",
|
||||||
|
"unplugin-element-plus": "^0.4.0",
|
||||||
|
"unplugin-vue-components": "^0.19.3",
|
||||||
|
"vite": "^2.9.5",
|
||||||
|
"vue-tsc": "^0.34.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// This starter template is using Vue 3 <script setup> SFCs
|
||||||
|
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||||
|
import SystemMenu from './components/SystemMenu.vue';
|
||||||
|
import SystemLayout from './components/SystemLayout.vue';
|
||||||
|
import "element-plus/dist/index.css";
|
||||||
|
import "funjiaui/dist/style.css";
|
||||||
|
import * as funjiaui from "funjiaui";
|
||||||
|
import axios from "funjia-axios";
|
||||||
|
import * as vue from "vue";
|
||||||
|
import lodashEs from "lodash-es";
|
||||||
|
import * as elementPlus from "element-plus";
|
||||||
|
|
||||||
|
window.vue = vue;
|
||||||
|
window.lodashEs = lodashEs;
|
||||||
|
window.funjiaui = funjiaui;
|
||||||
|
window.axios = axios;
|
||||||
|
window.elementPlus = elementPlus;
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<router-view />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
/* 滚动条 */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动槽 */
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
-webkit-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 滚动条滑块 */
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #999;
|
||||||
|
-webkit-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm,
|
||||||
|
UmByClassEnhance as UmTableClassEnhance
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "./api";
|
||||||
|
import MagnetOperate from './MagnetOperate.vue';
|
||||||
|
// import { h, ref } from "vue";
|
||||||
|
// import MagnetBase from './MagnetBase';
|
||||||
|
|
||||||
|
const tableName = "magnet";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class BatchMagnetLinks {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "资源名称", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "资源名称", fieldType: "textarea", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
name: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "保存路径", minWidth: 650 })
|
||||||
|
@tfcpd({ "lang": "", "def": "保存路径", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
savePath: string = "/movie/2025";
|
||||||
|
|
||||||
|
// @tcpd({ "lang": "", "def": "磁力地址", minWidth: 600 })
|
||||||
|
// @tfcpd({ "lang": "", "def": "磁力地址", fieldType: "custom", component: h(UmTableClassEnhance, { target: MagnetBase, data: "[]" }) })
|
||||||
|
// magnetAddress: string = ""
|
||||||
|
|
||||||
|
|
||||||
|
// // Getter 方法
|
||||||
|
// get content(): string {
|
||||||
|
// console.log("Getting name");
|
||||||
|
// return this.content1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Setter 方法
|
||||||
|
// set content(newName: string) {
|
||||||
|
// this.content1 = newName;
|
||||||
|
// this.operate = newName;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@tfcpd({
|
||||||
|
"lang": "", "def": "磁力列表", fieldType: "custom", component: MagnetOperate, rule: [{ "type": "require", message: "不能为空" }]
|
||||||
|
})
|
||||||
|
magnetList: any;
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addDynamic({ ...data }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getDynamic({ id: rowId }, tableName);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateDynamic({ ...params }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids: [rowId] }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+211
@@ -0,0 +1,211 @@
|
|||||||
|
import 'reflect-metadata';
|
||||||
|
import { h, reactive, render } from 'vue';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm,
|
||||||
|
UmDialog
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "./api";
|
||||||
|
import BatchMagnetLinks from "./BatchMagnetLinks";
|
||||||
|
import MagnetBase from './MagnetBase';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
function getRandomNumberBetween(min, max) {
|
||||||
|
// Math.random() 生成 [0, 1) 之间的随机数
|
||||||
|
// 乘以 (max - min + 1) 将范围扩展到 [0, max - min + 1)
|
||||||
|
// 加上 min 将范围偏移到 [min, max + 1)
|
||||||
|
// 使用 Math.floor 向下取整,确保结果是整数
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机延迟函数执行
|
||||||
|
* @param min
|
||||||
|
* @param max
|
||||||
|
*/
|
||||||
|
function randomDelay(min = 2000, max = 4000) {
|
||||||
|
const delay = getRandomNumberBetween(min, max);
|
||||||
|
console.log(`等待 ${delay} 毫秒...`);
|
||||||
|
return sleep(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const tableName = "magnet";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default class Magnet extends MagnetBase {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getDynamicList(params, tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addDynamic({ ...data }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getDynamic({ id: rowId }, tableName);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateDynamic({ ...params }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids: [rowId] }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:toolbar", "value": { "type": "批量删除", "priority": 5, "es": "onAfter", "dialogContent": "确定要删除选择的数据吗?" } })
|
||||||
|
onMutilDel = async (ids: any[]) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "自定义", "priority": 2, "es": "onAfter", title: "导入磁力信息"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onImportMagnet = async (params: any) => {
|
||||||
|
// 1. 定义一个组件
|
||||||
|
const MyComponent = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async onResetSubmit(data) {
|
||||||
|
// console.log('submit',data,this.magnetData);
|
||||||
|
if (data?.magnetList?.length > 0) {
|
||||||
|
const magnetList = data?.magnetList || [];
|
||||||
|
const resourceName = data?.name;
|
||||||
|
for (const item of magnetList) {
|
||||||
|
const magnet = new Magnet();
|
||||||
|
magnet.name = resourceName;
|
||||||
|
magnet.mgnetAddress = item.name;
|
||||||
|
const taskInfo = await api.offDownBaiduCloudPan({ magnet: item.name, savePath: data?.savePath });
|
||||||
|
console.log(taskInfo);
|
||||||
|
magnet.taskId = taskInfo?.data?.task_id;
|
||||||
|
const { code, msg } =
|
||||||
|
await api.addDynamic(magnet, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
// return { code: 1, message: msg };
|
||||||
|
ElMessage.error(msg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ElMessage.info("导入成功" + item.name);
|
||||||
|
}
|
||||||
|
await randomDelay(20000, 40000);
|
||||||
|
}
|
||||||
|
this.visible = false;
|
||||||
|
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onResetCancel() {
|
||||||
|
this.visible = false;
|
||||||
|
// console.log('cancel');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
console.log(this.visible);
|
||||||
|
return h(UmDialog, {
|
||||||
|
"modelValue": this.visible,
|
||||||
|
title: "批量磁力",
|
||||||
|
width: "1000px",
|
||||||
|
footer: false,
|
||||||
|
|
||||||
|
onUpdateModelValue: function (value) {
|
||||||
|
this.visible = value;
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
}, h(UmTableForm, {
|
||||||
|
target: BatchMagnetLinks,
|
||||||
|
data: this.magnetData,
|
||||||
|
onOk: this.onResetSubmit,
|
||||||
|
onCancel: this.onResetCancel,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 2. 使用 render 函数将组件渲染到页面上
|
||||||
|
const container = document.createElement('div');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
render(h(MyComponent), container);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import 'reflect-metadata';
|
||||||
|
import { h, render } from 'vue';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm,
|
||||||
|
UmDialog
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "./api";
|
||||||
|
import BatchMagnetLinks from "./BatchMagnetLinks";
|
||||||
|
|
||||||
|
const tableName = "magnet";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class MagnetBase {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "名称", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "名称", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
name: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "磁力地址", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "磁力地址", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
mgnetAddress: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "任务Id", minWidth: 120 })
|
||||||
|
taskId: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "下载状态", minWidth: 120 })
|
||||||
|
isDown: boolean = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-input type="textarea" v-model="magnetInfo"></el-input>
|
||||||
|
<div :style="{ maxHeight: '300px', overflowY: 'auto' }">
|
||||||
|
<um-table-class-enhance v-if="data.length" class="role-right" :target="MagnetOperateClass">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
<el-button @click="onHandle">处理磁力信息</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm,
|
||||||
|
UmByClassEnhance as UmTableClassEnhance
|
||||||
|
} from "funjiaui";
|
||||||
|
import MagnetBase from './MagnetBase';
|
||||||
|
import { ref, useAttrs, watch } from "vue";
|
||||||
|
|
||||||
|
const magnetInfo = ref("");
|
||||||
|
const data = ref([]);
|
||||||
|
const attrs = useAttrs();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
modelValue: any
|
||||||
|
}>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(n: "update:modelValue", url: string): void;
|
||||||
|
}>();
|
||||||
|
const onHandle = () => {
|
||||||
|
const magnetList = magnetInfo.value.split("\n");
|
||||||
|
magnetList.forEach((value, i) => {
|
||||||
|
if (value)
|
||||||
|
data.value.push({
|
||||||
|
id: new Date().getTime() + "_" + i,
|
||||||
|
name: decodeURIComponent(value)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
emit("update:modelValue", data.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MagnetOperateClass {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "名称", minWidth: 650 })
|
||||||
|
@tfcpd({ "lang": "", "def": "名称", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
name: string = ""
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return { data: data.value };
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
// console.log(rowId);
|
||||||
|
const magnetList = data.value;
|
||||||
|
const idx = magnetList.findIndex(item => item.id == rowId);
|
||||||
|
if (idx != -1)
|
||||||
|
data.value.splice(idx, 1);
|
||||||
|
emit("update:modelValue", data.value);
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:toolbar", "value": { "type": "批量删除", "priority": 5, "es": "onAfter", "dialogContent": "确定要删除选择的数据吗?" } })
|
||||||
|
onMutilDel = async (ids: any[]) => {
|
||||||
|
// console.log(ids);
|
||||||
|
data.value = data.value.filter(item => {
|
||||||
|
return !ids.includes(item.id);
|
||||||
|
})
|
||||||
|
emit("update:modelValue", data.value);
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "./api";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Notice {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "消息", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "消息", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
message: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "排序", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "排序", fieldType: "number", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
sort: number = 1;
|
||||||
|
|
||||||
|
static userId: any;
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getNoticeList(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addNotice({ ...data, userId: Notice.userId });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getNotice({ id: rowId });
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateNotice({ ...params, userId: Notice.userId });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteNotice({ ids: [rowId] });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "./api";
|
||||||
|
|
||||||
|
const tableName = "tag";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Tag {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "名称", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "名称", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
name: string = ""
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getDynamicList(params, tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addDynamic({ ...data }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getDynamic({ id: rowId }, tableName);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateDynamic({ ...params }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids: [rowId] }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @tcmd({
|
||||||
|
// "value": {
|
||||||
|
// "id": 1, "type": "customOperateEvent", "title": "详情",
|
||||||
|
// sort: 1,
|
||||||
|
// isShow: (rowData) => {
|
||||||
|
// if (rowData?.snaper_image > 0) {
|
||||||
|
// return true;
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// jumpEmployee = (rowId: number) => {
|
||||||
|
// return rowId;
|
||||||
|
// }
|
||||||
|
}
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
import axios from "funjia-axios";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Notice列表
|
||||||
|
*/
|
||||||
|
export const getNoticeList = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Notice详情
|
||||||
|
*/
|
||||||
|
export const getNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.get("/api/Notice", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加Notice
|
||||||
|
*/
|
||||||
|
export const addNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/add", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Notice
|
||||||
|
*/
|
||||||
|
export const updateNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/upd", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Notice
|
||||||
|
*/
|
||||||
|
export const deleteNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/delete", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Dynamic列表
|
||||||
|
*/
|
||||||
|
export const getDynamicList = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/list/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Dynamic详情
|
||||||
|
*/
|
||||||
|
export const getDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.get("/api/dynamic/" + tableName, { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加Dynamic
|
||||||
|
*/
|
||||||
|
export const addDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/add/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Dynamic
|
||||||
|
*/
|
||||||
|
export const updateDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/upd/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Dynamic
|
||||||
|
*/
|
||||||
|
export const deleteDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/delete/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 操作百度云盘api
|
||||||
|
export const offDownBaiduCloudPan = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/baiduCloudPan/offDown", params);
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "iconfont"; /* Project id 3015159 */
|
||||||
|
src: url('iconfont.woff2?t=1646121864615') format('woff2'),
|
||||||
|
url('iconfont.woff?t=1646121864615') format('woff'),
|
||||||
|
url('iconfont.ttf?t=1646121864615') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-family: "iconfont" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-a-bianzu171:before {
|
||||||
|
content: "\e66b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-duobianxing:before {
|
||||||
|
content: "\e697";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-radio-on:before {
|
||||||
|
content: "\ea6a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-zhibo-qingping:before {
|
||||||
|
content: "\e63a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-gouxuan11:before {
|
||||||
|
content: "\e628";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-weigouxuan:before {
|
||||||
|
content: "\e623";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-bianji1:before {
|
||||||
|
content: "\e607";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-shanchu:before {
|
||||||
|
content: "\e625";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-guanbi:before {
|
||||||
|
content: "\e611";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-danxuan_weixuanzhong:before {
|
||||||
|
content: "\e653";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-danxuan_xuanzhong:before {
|
||||||
|
content: "\e655";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-Shape:before {
|
||||||
|
content: "\e665";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-jiahaozhankaibeifen:before {
|
||||||
|
content: "\e664";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-jiahaozhankai:before {
|
||||||
|
content: "\e663";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-shangchuan:before {
|
||||||
|
content: "\e662";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-a-gonganjubeifen5:before {
|
||||||
|
content: "\e65e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-gonganju:before {
|
||||||
|
content: "\e65d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-duoxuan-xuanzhong:before {
|
||||||
|
content: "\e65c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-duoxuan-weixuan:before {
|
||||||
|
content: "\e659";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-xiala:before {
|
||||||
|
content: "\e6b9";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-dingweixiao:before {
|
||||||
|
content: "\e654";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-shanchu-:before {
|
||||||
|
content: "\e652";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daoru:before {
|
||||||
|
content: "\e651";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daochu:before {
|
||||||
|
content: "\e650";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-xiazai:before {
|
||||||
|
content: "\e64f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-tianjia:before {
|
||||||
|
content: "\e64e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-rili_calendar:before {
|
||||||
|
content: "\e64d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-bianji:before {
|
||||||
|
content: "\e648";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-mimabeifen:before {
|
||||||
|
content: "\e638";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-qietu:before {
|
||||||
|
content: "\e637";
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
{
|
||||||
|
"id": "3015159",
|
||||||
|
"name": "仲恺综合治理平台",
|
||||||
|
"font_family": "iconfont",
|
||||||
|
"css_prefix_text": "icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "27921080",
|
||||||
|
"name": "派出所下的二级图标",
|
||||||
|
"font_class": "a-bianzu171",
|
||||||
|
"unicode": "e66b",
|
||||||
|
"unicode_decimal": 58987
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "9706996",
|
||||||
|
"name": "多边形",
|
||||||
|
"font_class": "duobianxing",
|
||||||
|
"unicode": "e697",
|
||||||
|
"unicode_decimal": 59031
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "18175740",
|
||||||
|
"name": "圆形",
|
||||||
|
"font_class": "radio-on",
|
||||||
|
"unicode": "ea6a",
|
||||||
|
"unicode_decimal": 60010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26849757",
|
||||||
|
"name": "zhibo-qingping",
|
||||||
|
"font_class": "zhibo-qingping",
|
||||||
|
"unicode": "e63a",
|
||||||
|
"unicode_decimal": 58938
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "16368199",
|
||||||
|
"name": "勾选1",
|
||||||
|
"font_class": "gouxuan11",
|
||||||
|
"unicode": "e628",
|
||||||
|
"unicode_decimal": 58920
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "351775",
|
||||||
|
"name": "未勾选",
|
||||||
|
"font_class": "weigouxuan",
|
||||||
|
"unicode": "e623",
|
||||||
|
"unicode_decimal": 58915
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4880425",
|
||||||
|
"name": "编辑",
|
||||||
|
"font_class": "bianji1",
|
||||||
|
"unicode": "e607",
|
||||||
|
"unicode_decimal": 58887
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26535246",
|
||||||
|
"name": "删除",
|
||||||
|
"font_class": "shanchu",
|
||||||
|
"unicode": "e625",
|
||||||
|
"unicode_decimal": 58917
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4942640",
|
||||||
|
"name": "关闭",
|
||||||
|
"font_class": "guanbi",
|
||||||
|
"unicode": "e611",
|
||||||
|
"unicode_decimal": 58897
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6548521",
|
||||||
|
"name": "单选_未选中",
|
||||||
|
"font_class": "danxuan_weixuanzhong",
|
||||||
|
"unicode": "e653",
|
||||||
|
"unicode_decimal": 58963
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6548524",
|
||||||
|
"name": "单选_选中",
|
||||||
|
"font_class": "danxuan_xuanzhong",
|
||||||
|
"unicode": "e655",
|
||||||
|
"unicode_decimal": 58965
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507365",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "Shape",
|
||||||
|
"unicode": "e665",
|
||||||
|
"unicode_decimal": 58981
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507356",
|
||||||
|
"name": "jiahaozhankai备份",
|
||||||
|
"font_class": "jiahaozhankaibeifen",
|
||||||
|
"unicode": "e664",
|
||||||
|
"unicode_decimal": 58980
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507350",
|
||||||
|
"name": "jiahaozhankai",
|
||||||
|
"font_class": "jiahaozhankai",
|
||||||
|
"unicode": "e663",
|
||||||
|
"unicode_decimal": 58979
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507342",
|
||||||
|
"name": "上传照片",
|
||||||
|
"font_class": "shangchuan",
|
||||||
|
"unicode": "e662",
|
||||||
|
"unicode_decimal": 58978
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507072",
|
||||||
|
"name": "街道,区域",
|
||||||
|
"font_class": "a-gonganjubeifen5",
|
||||||
|
"unicode": "e65e",
|
||||||
|
"unicode_decimal": 58974
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507064",
|
||||||
|
"name": "派出所",
|
||||||
|
"font_class": "gonganju",
|
||||||
|
"unicode": "e65d",
|
||||||
|
"unicode_decimal": 58973
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26507030",
|
||||||
|
"name": "复选框-选中",
|
||||||
|
"font_class": "duoxuan-xuanzhong",
|
||||||
|
"unicode": "e65c",
|
||||||
|
"unicode_decimal": 58972
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506763",
|
||||||
|
"name": "复选框-未选中",
|
||||||
|
"font_class": "duoxuan-weixuan",
|
||||||
|
"unicode": "e659",
|
||||||
|
"unicode_decimal": 58969
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "672036",
|
||||||
|
"name": "下拉",
|
||||||
|
"font_class": "xiala",
|
||||||
|
"unicode": "e6b9",
|
||||||
|
"unicode_decimal": 59065
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506542",
|
||||||
|
"name": "定位",
|
||||||
|
"font_class": "dingweixiao",
|
||||||
|
"unicode": "e654",
|
||||||
|
"unicode_decimal": 58964
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506492",
|
||||||
|
"name": "删除",
|
||||||
|
"font_class": "shanchu-",
|
||||||
|
"unicode": "e652",
|
||||||
|
"unicode_decimal": 58962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506468",
|
||||||
|
"name": "导入",
|
||||||
|
"font_class": "daoru",
|
||||||
|
"unicode": "e651",
|
||||||
|
"unicode_decimal": 58961
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506447",
|
||||||
|
"name": "导出",
|
||||||
|
"font_class": "daochu",
|
||||||
|
"unicode": "e650",
|
||||||
|
"unicode_decimal": 58960
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506428",
|
||||||
|
"name": "下载",
|
||||||
|
"font_class": "xiazai",
|
||||||
|
"unicode": "e64f",
|
||||||
|
"unicode_decimal": 58959
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506404",
|
||||||
|
"name": "添加",
|
||||||
|
"font_class": "tianjia",
|
||||||
|
"unicode": "e64e",
|
||||||
|
"unicode_decimal": 58958
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26506240",
|
||||||
|
"name": "日期",
|
||||||
|
"font_class": "rili_calendar",
|
||||||
|
"unicode": "e64d",
|
||||||
|
"unicode_decimal": 58957
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26505995",
|
||||||
|
"name": "编辑",
|
||||||
|
"font_class": "bianji",
|
||||||
|
"unicode": "e648",
|
||||||
|
"unicode_decimal": 58952
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26462764",
|
||||||
|
"name": "密码",
|
||||||
|
"font_class": "mimabeifen",
|
||||||
|
"unicode": "e638",
|
||||||
|
"unicode_decimal": 58936
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "26462757",
|
||||||
|
"name": "用户",
|
||||||
|
"font_class": "qietu",
|
||||||
|
"unicode": "e637",
|
||||||
|
"unicode_decimal": 58935
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,278 @@
|
|||||||
|
import axios from "funjia-axios";
|
||||||
|
// import imgList from "../../../public/data/image_cache.json";
|
||||||
|
// import serviceInfo from "../../../public/data/get_service_info.json";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
export const login = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/login", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*/
|
||||||
|
export const udpdatePwd = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/user/password/update", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取系统信息
|
||||||
|
*/
|
||||||
|
export const getSytemInfo = (): Promise<any> => {
|
||||||
|
return axios.get("/api/get/system");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ipcId获取抓拍图片列表
|
||||||
|
*/
|
||||||
|
export const getCaputreImgListByIpcId = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/query/device/obejct/image/cache", params);
|
||||||
|
// return imgList;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志级别列表
|
||||||
|
*/
|
||||||
|
export const getLevelList = (): Promise<any> => {
|
||||||
|
return axios.post("/api/get/log/level");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志列表
|
||||||
|
*/
|
||||||
|
export const getLogList = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/get/log/last", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置日志级别
|
||||||
|
*/
|
||||||
|
export const setLogLevel = (params: any): Promise<any> => {
|
||||||
|
return axios.post(`/set/log/level/${params.level}`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重启系统
|
||||||
|
*/
|
||||||
|
export const restartSystem = (): Promise<any> => {
|
||||||
|
return axios.get('/api/system/reboot');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重启程序
|
||||||
|
*/
|
||||||
|
export const restartApp = (): Promise<any> => {
|
||||||
|
return axios.get('/api/system/restart');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取服务状态
|
||||||
|
*/
|
||||||
|
export const getServiceStatus = (): Promise<any> => {
|
||||||
|
return axios.get('/get/service/info');
|
||||||
|
// return serviceInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置服务
|
||||||
|
*/
|
||||||
|
export const setService = (params: any): Promise<any> => {
|
||||||
|
return axios.post('/api/set/service/manager', params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取TravelInformation列表
|
||||||
|
*/
|
||||||
|
export const getTravelInformationList = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/TravelInformation/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取TravelInformation详情
|
||||||
|
*/
|
||||||
|
export const getTravelInformation = (params: any): Promise<any> => {
|
||||||
|
return axios.get("/api/travelInformation", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加TravelInformation
|
||||||
|
*/
|
||||||
|
export const addTravelInformation = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/TravelInformation/add", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改TravelInformation
|
||||||
|
*/
|
||||||
|
export const updateTravelInformation = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/TravelInformation/upd", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除TravelInformation
|
||||||
|
*/
|
||||||
|
export const deleteTravelInformation = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/TravelInformation/delete", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Employee列表
|
||||||
|
*/
|
||||||
|
export const getEmployeeList = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Employee/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Employee详情
|
||||||
|
*/
|
||||||
|
export const getEmployee = (params: any): Promise<any> => {
|
||||||
|
return axios.get("/api/Employee", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加Employee
|
||||||
|
*/
|
||||||
|
export const addEmployee = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Employee/add", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Employee
|
||||||
|
*/
|
||||||
|
export const updateEmployee = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Employee/upd", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Employee
|
||||||
|
*/
|
||||||
|
export const deleteEmployee = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Employee/delete", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Employee登录
|
||||||
|
*/
|
||||||
|
export const employeeLogin = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Employee/login", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Notice列表
|
||||||
|
*/
|
||||||
|
export const getNoticeList = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Notice详情
|
||||||
|
*/
|
||||||
|
export const getNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.get("/api/Notice", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加Notice
|
||||||
|
*/
|
||||||
|
export const addNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/add", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Notice
|
||||||
|
*/
|
||||||
|
export const updateNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/upd", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Notice
|
||||||
|
*/
|
||||||
|
export const deleteNotice = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/Notice/delete", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取QA列表
|
||||||
|
*/
|
||||||
|
export const getQAList = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/QA/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取QA详情
|
||||||
|
*/
|
||||||
|
export const getQA = (params: any): Promise<any> => {
|
||||||
|
return axios.get("/api/QA", { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加QA
|
||||||
|
*/
|
||||||
|
export const addQA = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/QA/add", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改QA
|
||||||
|
*/
|
||||||
|
export const updateQA = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/QA/upd", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除QA
|
||||||
|
*/
|
||||||
|
export const deleteQA = (params: any): Promise<any> => {
|
||||||
|
return axios.post("/api/QA/delete", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Dynamic列表
|
||||||
|
*/
|
||||||
|
export const getDynamicList = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/list/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Dynamic详情
|
||||||
|
*/
|
||||||
|
export const getDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.get("/api/dynamic/" + tableName, { params });
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加Dynamic
|
||||||
|
*/
|
||||||
|
export const addDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/add/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改Dynamic
|
||||||
|
*/
|
||||||
|
export const updateDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/upd/" + tableName, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Dynamic
|
||||||
|
*/
|
||||||
|
export const deleteDynamic = (params: any, tableName: string): Promise<any> => {
|
||||||
|
return axios.post("/api/dynamic/delete/" + tableName, params);
|
||||||
|
};
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import 'element-plus/es/components/message/style/css'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
// axios.defaults.baseURL = ""; // 请求后台地址
|
||||||
|
axios.defaults.headers.post["Content-Type"] = "application/json;charset=utf-8";
|
||||||
|
|
||||||
|
interface LogOutCodesProps {
|
||||||
|
status: number;
|
||||||
|
code: number;
|
||||||
|
msg?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.interceptors.request.use(
|
||||||
|
(config: AxiosRequestConfig) => {
|
||||||
|
// token授权
|
||||||
|
const jwtToken: string = Cookies.get("Authorization") ?? "";
|
||||||
|
config.headers = config.headers || {};
|
||||||
|
config.headers.Authorization = `${jwtToken}`;
|
||||||
|
// 缓存问题
|
||||||
|
config.headers["Cache-Control"] = "no-cache";
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
axios.interceptors.response.use(
|
||||||
|
(response: AxiosResponse) => {
|
||||||
|
const xhr: any = response.data ?? {};
|
||||||
|
const { code, msg: resultMsg } = xhr;
|
||||||
|
// 需要退出重登的code和msg
|
||||||
|
let msg: string = "";
|
||||||
|
switch (code) {
|
||||||
|
case 9:
|
||||||
|
msg = "请重新登录";
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
msg = "授权过期,请重新登录";
|
||||||
|
break;
|
||||||
|
case 27:
|
||||||
|
msg = "未安装License或License已过期";
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
msg = "License权限不足";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (code) {
|
||||||
|
ElMessage.error(msg || resultMsg || "系统异常");
|
||||||
|
}
|
||||||
|
return xhr;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
const response: any = error.response ?? {};
|
||||||
|
const { data, status } = response;
|
||||||
|
const { code, reason } = data;
|
||||||
|
let msg: string = "";
|
||||||
|
// 获取错误提示
|
||||||
|
switch (status) {
|
||||||
|
case 400:
|
||||||
|
msg =
|
||||||
|
code === 17
|
||||||
|
? `异地登录,登录IP为${data.data},请重新登录`
|
||||||
|
: "请求错误";
|
||||||
|
break;
|
||||||
|
case 401:
|
||||||
|
msg = reason || "鉴权失败";
|
||||||
|
break;
|
||||||
|
case 403:
|
||||||
|
msg = "拒绝访问";
|
||||||
|
break;
|
||||||
|
case 404:
|
||||||
|
msg = "请求错误,未找到该资源";
|
||||||
|
break;
|
||||||
|
case 405:
|
||||||
|
msg = "请求方法未允许";
|
||||||
|
break;
|
||||||
|
case 408:
|
||||||
|
msg = "请求超时";
|
||||||
|
break;
|
||||||
|
case 413:
|
||||||
|
msg = "请求数据过多";
|
||||||
|
break;
|
||||||
|
case 500:
|
||||||
|
msg = "服务器端出错";
|
||||||
|
break;
|
||||||
|
case 501:
|
||||||
|
msg = "网络未实现";
|
||||||
|
break;
|
||||||
|
case 503:
|
||||||
|
msg = "服务不可用";
|
||||||
|
break;
|
||||||
|
case 504:
|
||||||
|
msg = "网络超时";
|
||||||
|
break;
|
||||||
|
case 505:
|
||||||
|
msg = "http版本不支持该请求";
|
||||||
|
break;
|
||||||
|
case 502:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ElMessage.error(msg);
|
||||||
|
return Promise.reject(error).catch(() => {
|
||||||
|
if (401 == status) {
|
||||||
|
window.location.href = "/";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default axios;
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* 获取目标类型的名称 0:人脸, 1:自行车, 2:巴士, 3:小汽车, 4:电动车|摩托车, 5:人体, 6:三轮车,7货车、8车牌、9推车,10鸟、11猫,12 狗,13老鼠
|
||||||
|
* @param objectType
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getObjectTypeName = (objectType: TObjectType) => {
|
||||||
|
switch (objectType) {
|
||||||
|
case 0:
|
||||||
|
return "人脸";
|
||||||
|
case 1:
|
||||||
|
return "自行车";
|
||||||
|
case 2:
|
||||||
|
return "巴士";
|
||||||
|
case 3:
|
||||||
|
return "小汽车";
|
||||||
|
case 4:
|
||||||
|
return "电动车|摩托车";
|
||||||
|
case 5:
|
||||||
|
return "人体";
|
||||||
|
case 6:
|
||||||
|
return "三轮车";
|
||||||
|
case 7:
|
||||||
|
return "货车";
|
||||||
|
case 8:
|
||||||
|
return "车牌";
|
||||||
|
case 9:
|
||||||
|
return "推车";
|
||||||
|
case 10:
|
||||||
|
return "鸟";
|
||||||
|
case 11:
|
||||||
|
return "猫";
|
||||||
|
case 12:
|
||||||
|
return "狗";
|
||||||
|
case 13:
|
||||||
|
return "老鼠";
|
||||||
|
default:
|
||||||
|
return "--";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 解决加减乘除中浮点数精度问题
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arg1 第一位数字
|
||||||
|
* arg2 第二位数字
|
||||||
|
* type 运算符类型 加add, 减reduce,乘ride,除except
|
||||||
|
*/
|
||||||
|
export const FloatPoint = (arg1: number, arg2: number, type: 'add' | 'reduce' | 'ride' | 'except') => {
|
||||||
|
let r1: number = 0;
|
||||||
|
let r2: number = 0;
|
||||||
|
try {
|
||||||
|
r1 = arg1.toString().split(".")[1].length;
|
||||||
|
} catch (e) {
|
||||||
|
r1 = 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
r2 = arg2.toString().split(".")[1].length;
|
||||||
|
} catch (e) {
|
||||||
|
r2 = 0;
|
||||||
|
}
|
||||||
|
const c: number = Math.abs(r1 - r2); // 位数差的绝对值
|
||||||
|
const m: number = Math.pow(10, Math.max(r1, r2)); // 较大数的幂
|
||||||
|
if (c > 0) {
|
||||||
|
// 位数相差
|
||||||
|
const cm: number = Math.pow(10, c);
|
||||||
|
if (r1 > r2) {
|
||||||
|
arg1 = Number(arg1.toString().replace(".", "")); // 转化成数字
|
||||||
|
arg2 = Number(arg2.toString().replace(".", "")) * cm;
|
||||||
|
} else {
|
||||||
|
arg1 = Number(arg1.toString().replace(".", "")) * cm;
|
||||||
|
arg2 = Number(arg2.toString().replace(".", ""));
|
||||||
|
}
|
||||||
|
} else { // 位数相等
|
||||||
|
arg1 = Number(arg1.toString().replace(".", ""));
|
||||||
|
arg2 = Number(arg2.toString().replace(".", ""));
|
||||||
|
}
|
||||||
|
let res: any = null;
|
||||||
|
if (type === 'add') {
|
||||||
|
res = (arg1 + arg2) / m;
|
||||||
|
} else if (type === 'reduce') {
|
||||||
|
res = (arg1 - arg2) / m;
|
||||||
|
} else if (type === 'ride') {
|
||||||
|
res = (arg1 * arg2) / m / m;
|
||||||
|
} else if (type === 'except') {
|
||||||
|
res = (arg1 / arg2);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对字符串保留小数
|
||||||
|
* @param value 原始值,有可能大于1
|
||||||
|
* @param num 位数
|
||||||
|
*/
|
||||||
|
export const toFixed = (str: any, num: number = 2) => {
|
||||||
|
try {
|
||||||
|
if (typeof (str) === "string") {
|
||||||
|
str = parseFloat(str);
|
||||||
|
} else if (typeof (str) === "number") {
|
||||||
|
str = str;
|
||||||
|
} else {
|
||||||
|
str = parseFloat(str);
|
||||||
|
}
|
||||||
|
str = FloatPoint(str, 100, 'ride');
|
||||||
|
str = str.toString(); // 字符串值
|
||||||
|
const pointIdx = str.indexOf("."); // 字符串中小数点的位置
|
||||||
|
if (pointIdx !== -1) {
|
||||||
|
if (num > 0) {
|
||||||
|
// 存在小数点的情况下
|
||||||
|
// 最多保留num位小数
|
||||||
|
str = str.substring(0, pointIdx + (num + 1));
|
||||||
|
// 小数位小于num位的情况下,在末尾补零
|
||||||
|
const decimalStr = str.substring(pointIdx + 1); // 小数位字符串
|
||||||
|
if (decimalStr.length < num) {
|
||||||
|
for (let i = 0; i < num - decimalStr.length; i++) {
|
||||||
|
str += "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = str.substring(0, pointIdx);
|
||||||
|
return parseFloat(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return parseFloat(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encode(str) {
|
||||||
|
// 对字符串进行编码
|
||||||
|
const encode = encodeURI(str);
|
||||||
|
// 对编码的字符串转化base64
|
||||||
|
const base64 = btoa(encode);
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decode(base64) {
|
||||||
|
// 对base64转编码
|
||||||
|
const decode = atob(base64);
|
||||||
|
// 编码转字符串
|
||||||
|
const str = decodeURI(decode);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="'angle ' + identity + ' ' + direction">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
// 箭头方向
|
||||||
|
export enum EDirection {
|
||||||
|
LeftTop = "left-top",
|
||||||
|
LeftBottom = "left-bottom",
|
||||||
|
RightTop = "right-top",
|
||||||
|
RightBottom = "right-bottom"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 身份类型
|
||||||
|
export enum EIdentity {
|
||||||
|
// 重点人员
|
||||||
|
Suspect = "suspect",
|
||||||
|
// 陌生人
|
||||||
|
Stranger = "stranger",
|
||||||
|
// 居民
|
||||||
|
Resident = "resident",
|
||||||
|
// 未归档
|
||||||
|
Unknow = "unknow",
|
||||||
|
// 其它
|
||||||
|
Other = "other"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script setup lang="ts">
|
||||||
|
withDefaults(defineProps<{ identity: EIdentity, direction: EDirection }>(), {
|
||||||
|
identity: EIdentity.Stranger,
|
||||||
|
direction: EDirection.LeftTop
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
$suspect-color:#ff5757;
|
||||||
|
$stranger-color:#f9db12;
|
||||||
|
$residents-color:#12DB68;
|
||||||
|
$unknow-color:#989898;
|
||||||
|
$primary1_color:#00C9DE;
|
||||||
|
|
||||||
|
|
||||||
|
@mixin borderStyle($color) {
|
||||||
|
height: 8px;
|
||||||
|
width: 8px;
|
||||||
|
border-top: 3px solid $color;
|
||||||
|
border-left: 3px solid $color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin angle-block($color) {
|
||||||
|
&.left-top {
|
||||||
|
@include borderStyle($color);
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left-bottom {
|
||||||
|
@include borderStyle($color);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right-top {
|
||||||
|
@include borderStyle($color);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right-bottom {
|
||||||
|
@include borderStyle($color);
|
||||||
|
transform: rotate(180deg);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.angle {
|
||||||
|
|
||||||
|
// 重点人员
|
||||||
|
&.suspect {
|
||||||
|
@include angle-block($suspect-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 陌生人
|
||||||
|
&.stranger {
|
||||||
|
@include angle-block($stranger-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 居民
|
||||||
|
&.resident {
|
||||||
|
@include angle-block($residents-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未归档
|
||||||
|
&.unknow {
|
||||||
|
@include angle-block($unknow-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其它
|
||||||
|
&.other {
|
||||||
|
@include angle-block($primary1_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<object-rect :top="top" :left="left" :width="-(left - right)" :height="-(top - bottom)"></object-rect>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
// import { EIdentity } from './Angle.vue';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
const props = defineProps<{
|
||||||
|
top: number,
|
||||||
|
right: number,
|
||||||
|
bottom: number,
|
||||||
|
left: number
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<codemirror v-model="value" placeholder="Code goes here..." :style="{ height: '400px' }" :autofocus="true"
|
||||||
|
:indent-with-tab="true" :tab-size="2" :extensions="extensions" @ready="handleReady" @change="log('change', $event)"
|
||||||
|
@focus="log('focus', $event)" @blur="log('blur', $event)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import { Codemirror } from 'vue-codemirror'
|
||||||
|
import { javascript } from '@codemirror/lang-javascript'
|
||||||
|
// import { oneDark } from '@codemirror/theme-one-dark'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
Codemirror
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const code = ref(`console.log('Hello, world!')`)
|
||||||
|
const extensions = [javascript()]
|
||||||
|
|
||||||
|
// Codemirror EditorView instance ref
|
||||||
|
const view = shallowRef()
|
||||||
|
const handleReady = (payload) => {
|
||||||
|
view.value = payload.view
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status is available at all times via Codemirror EditorView
|
||||||
|
const getCodemirrorStates = () => {
|
||||||
|
const state = view.value.state
|
||||||
|
const ranges = state.selection.ranges
|
||||||
|
const selected = ranges.reduce((r, range) => r + range.to - range.from, 0)
|
||||||
|
const cursor = ranges[0].anchor
|
||||||
|
const length = state.doc.length
|
||||||
|
const lines = state.doc.lines
|
||||||
|
// more state info ...
|
||||||
|
// return ...
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
extensions,
|
||||||
|
handleReady,
|
||||||
|
log: console.log
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<template>
|
||||||
|
<p class="el-message__content">{{ getMsgTempalte ? getMsgTempalte(countDownTime) : countDownTime }}</p>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onBeforeMount, ref, onBeforeUnmount } from "vue";
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
timespan?: number,
|
||||||
|
getMsgTempalte: (value: number) => string
|
||||||
|
}>(), {
|
||||||
|
timespan: 3
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(n: 'next'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const countDownTime = ref(props.timespan);
|
||||||
|
const timeout = ref();
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
timeout.value = setInterval(() => {
|
||||||
|
if (countDownTime.value >= 1) {
|
||||||
|
countDownTime.value -= 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clearInterval(timeout.value);
|
||||||
|
emit('next');
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearInterval(timeout.value);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<el-tag v-for="tag in dynamicTags" :key="tag" class="mx-1" closable :disable-transitions="false"
|
||||||
|
@close="handleClose(tag)">
|
||||||
|
{{ tag }}
|
||||||
|
</el-tag>
|
||||||
|
<el-input v-if="inputVisible" ref="InputRef" v-model="inputValue" class="ml-1 w-20" size="small"
|
||||||
|
@keyup.enter="handleInputConfirm" @blur="handleInputConfirm" />
|
||||||
|
<el-button v-else class="button-new-tag ml-1" size="small" @click="showInput">
|
||||||
|
+ New Tag
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.mx-1 {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { nextTick, ref } from 'vue'
|
||||||
|
import { ElInput } from 'element-plus'
|
||||||
|
|
||||||
|
const props = defineProps<{ modelValue: [] }>();
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(
|
||||||
|
e: "update:modelValue",
|
||||||
|
val: string | number | (string | number)[] | undefined
|
||||||
|
): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const inputValue = ref('')
|
||||||
|
const dynamicTags = ref(props.modelValue)
|
||||||
|
const inputVisible = ref(false)
|
||||||
|
const InputRef = ref<InstanceType<typeof ElInput>>()
|
||||||
|
|
||||||
|
const handleClose = (tag: string) => {
|
||||||
|
dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1)
|
||||||
|
emits('update:modelValue', dynamicTags.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const showInput = () => {
|
||||||
|
inputVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
InputRef.value!.input!.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleInputConfirm = () => {
|
||||||
|
if (inputValue.value) {
|
||||||
|
dynamicTags.value.push(inputValue.value)
|
||||||
|
emits('update:modelValue', dynamicTags.value)
|
||||||
|
}
|
||||||
|
inputVisible.value = false
|
||||||
|
inputValue.value = ''
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['img-preview']">
|
||||||
|
<vue-cropper :key="id" ref="cropper" :src="imgUrl" alt="" :autoCrop="false" dragMode="move" :background="false"
|
||||||
|
:viewMode="2" :toggleDragModeOnDblclick="false" @ready="onReady" @crop="onCrop" @zoom="onZoom" />
|
||||||
|
<div :class="$style['mask']">
|
||||||
|
<calc-rect-dock :top="rectPosition.top" :right="rectPosition.right" :bottom="rectPosition.bottom"
|
||||||
|
:left="rectPosition.left"></calc-rect-dock>
|
||||||
|
</div>
|
||||||
|
<div :class="$style['prev']" @click="$emit('imgIdxChange', -1)">
|
||||||
|
<el-icon>
|
||||||
|
<d-arrow-left />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<div :class="$style['next']" @click="$emit('imgIdxChange', 1)">
|
||||||
|
<el-icon>
|
||||||
|
<d-arrow-right />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import VueCropper from 'vue-cropperjs';
|
||||||
|
import 'cropperjs/dist/cropper.css';
|
||||||
|
import { reactive, ref, onBeforeMount, watch } from "vue";
|
||||||
|
import { computed } from '@vue/reactivity';
|
||||||
|
import { merge, cloneDeep } from "lodash-es";
|
||||||
|
import {
|
||||||
|
DArrowLeft,
|
||||||
|
DArrowRight,
|
||||||
|
} from "@element-plus/icons-vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: "",
|
||||||
|
imgUrl: "",
|
||||||
|
position: "",
|
||||||
|
}>();
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(n: 'imgIdxChange', value: TImgPreviewIdx): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const cropper = ref();
|
||||||
|
const cropOption = reactive({
|
||||||
|
ratio: 1,
|
||||||
|
delta: { deltaX: 0, deltaY: 0 }
|
||||||
|
});
|
||||||
|
const rectPosition = reactive({
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0
|
||||||
|
});
|
||||||
|
const defRatio = ref(0);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
initRectPosition();
|
||||||
|
})
|
||||||
|
|
||||||
|
watch([cropOption, () => props.id], () => {
|
||||||
|
initRectPosition();
|
||||||
|
})
|
||||||
|
|
||||||
|
const initRectPosition = () => {
|
||||||
|
const rectOption: any = formatRectPosition(cloneDeep(props.position)) || {};
|
||||||
|
merge(rectPosition, getStyle(rectOption));
|
||||||
|
}
|
||||||
|
|
||||||
|
const initCropOption = (e) => {
|
||||||
|
const canvasData: any = e.target?.cropper?.canvasData;
|
||||||
|
if (canvasData) {
|
||||||
|
if (e?.detail?.ratio && e.detail.ratio >= defRatio.value) {
|
||||||
|
merge(cropOption, {
|
||||||
|
ratio: e.detail.ratio,
|
||||||
|
delta: {
|
||||||
|
deltaX: canvasData.left,
|
||||||
|
deltaY: canvasData.top
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
merge(cropOption, {
|
||||||
|
delta: {
|
||||||
|
deltaX: canvasData.left,
|
||||||
|
deltaY: canvasData.top
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片渲染完成事件
|
||||||
|
* @param e
|
||||||
|
*/
|
||||||
|
const onReady = (e: any) => {
|
||||||
|
const canvasData: any = e.target?.cropper?.canvasData;
|
||||||
|
if (canvasData) {
|
||||||
|
defRatio.value = canvasData.width / e.target.width;
|
||||||
|
merge(cropOption, {
|
||||||
|
ratio: defRatio.value,
|
||||||
|
delta: { deltaX: 0, deltaY: 0 }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCrop = (e) => {
|
||||||
|
initCropOption(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onZoom = (e) => {
|
||||||
|
initCropOption(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化矩形框位置信息
|
||||||
|
* @param position json字符串
|
||||||
|
*/
|
||||||
|
const formatRectPosition = (position: any) => {
|
||||||
|
const fpm: any = {};
|
||||||
|
let rectInfo: any = {};
|
||||||
|
if (typeof (position) === "string") {
|
||||||
|
try {
|
||||||
|
rectInfo = JSON.parse(position);
|
||||||
|
const { face_rect, object_rect } = rectInfo;
|
||||||
|
if (face_rect) {
|
||||||
|
fpm.top = face_rect.top;
|
||||||
|
fpm.right = face_rect.right;
|
||||||
|
fpm.bottom = face_rect.bottom;
|
||||||
|
fpm.left = face_rect.left;
|
||||||
|
}
|
||||||
|
else if (object_rect) {
|
||||||
|
fpm.top = object_rect.top;
|
||||||
|
fpm.right = object_rect.right;
|
||||||
|
fpm.bottom = object_rect.bottom;
|
||||||
|
fpm.left = object_rect.left;
|
||||||
|
fpm.type = 2;//ERectType.Body;
|
||||||
|
}
|
||||||
|
return fpm;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("小图位置信息有误", position);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (position.face_rect) {
|
||||||
|
return position.face_rect;
|
||||||
|
}
|
||||||
|
else if (position.object_rect) {
|
||||||
|
return position.object_rect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.warn("小图位置信息有误", position);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定位矩形框
|
||||||
|
*/
|
||||||
|
const getStyle = (position: any) => {
|
||||||
|
const faceRect = position;
|
||||||
|
const { ratio, delta } = cropOption;
|
||||||
|
if (ratio != -1) {
|
||||||
|
for (const item in faceRect) {
|
||||||
|
if (["top", "right", "bottom", "left"].includes(item))
|
||||||
|
faceRect[item] = parseFloat(faceRect[item]) * ratio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
top: faceRect.top + delta.deltaY,
|
||||||
|
left: faceRect.left + delta.deltaX,
|
||||||
|
bottom: faceRect.bottom + delta.deltaY,
|
||||||
|
right: faceRect.right + delta.deltaX,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.img-preview) {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
:local(.mask) {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
|
||||||
|
:local(.prev),
|
||||||
|
:local(.next) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.prev),
|
||||||
|
:local(.next) {
|
||||||
|
position: absolute;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
background-color: rgb(10 10 10 / 20%);
|
||||||
|
line-height: 100px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none;
|
||||||
|
pointer-events: painted;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.prev) {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.next) {
|
||||||
|
right: 0;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
<system-layout>
|
||||||
|
<template #sidebar>
|
||||||
|
<system-menu menuIdx="1-1" :parentIdxList="[1]" />
|
||||||
|
</template>
|
||||||
|
<template #content>
|
||||||
|
<router-view></router-view>
|
||||||
|
</template>
|
||||||
|
</system-layout>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="['face-identity-rect', getRootClassName(), identity].join(' ')"
|
||||||
|
:style="{ width: width + 'px', height: height + 'px' }">
|
||||||
|
<angle :identity="identity" :direction="EDirection.LeftTop"></angle>
|
||||||
|
<angle :identity="identity" :direction="EDirection.LeftBottom"></angle>
|
||||||
|
<angle :identity="identity" :direction="EDirection.RightTop"></angle>
|
||||||
|
<angle :identity="identity" :direction="EDirection.RightBottom"></angle>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { EDirection, EIdentity } from "./Angle.vue";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const props: any = withDefaults(defineProps<{
|
||||||
|
identity: EIdentity, type: number,
|
||||||
|
width: number, height: number,
|
||||||
|
top: number,
|
||||||
|
left: number
|
||||||
|
}>(), {
|
||||||
|
identity: EIdentity.Resident,
|
||||||
|
type: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
const topVar = computed(() => props.top + 'px')
|
||||||
|
const leftVar = computed(() => props.left + 'px')
|
||||||
|
|
||||||
|
|
||||||
|
const getRootClassName = () => {
|
||||||
|
// if (props.type == 1)
|
||||||
|
// return "face-rect";
|
||||||
|
// else
|
||||||
|
return "body-rect";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.face-identity-rect {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
top: v-bind(topVar);
|
||||||
|
left: v-bind(leftVar);
|
||||||
|
|
||||||
|
&.body-rect {
|
||||||
|
//.face-rect {
|
||||||
|
// background-color: rgba(255, 140, 0, .19);
|
||||||
|
border: solid 2px #ff8c00;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.angle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['upload']" @change="onFileChange">
|
||||||
|
<input ref="fileRef" :accept="accept" v-show="false" type="file" />
|
||||||
|
<el-input :model-value="fileName" :disabled="true" :style="{ width: '200px' }" />
|
||||||
|
<el-button :class="$style['scan']" @click="onPreUpload">浏览</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
withDefaults(defineProps<{
|
||||||
|
accept?: any
|
||||||
|
}>(), {
|
||||||
|
accept: '*'
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(n: "fileChange", file: File): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const fileRef = ref();
|
||||||
|
const fileName = ref();
|
||||||
|
|
||||||
|
const onFileChange = (e: any) => {
|
||||||
|
const files = e.target.files;
|
||||||
|
fileName.value = files?.[0]?.name;
|
||||||
|
emit('fileChange', files?.[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPreUpload = () => {
|
||||||
|
fileRef.value.value = "";
|
||||||
|
fileRef.value?.click();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.upload) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
:local(.scan) {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<slot name="header" :style="{ height: '80px' }">
|
||||||
|
<home-header></home-header>
|
||||||
|
</slot>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :style="{
|
||||||
|
height: 'calc(100% - 80px)'
|
||||||
|
}">
|
||||||
|
<el-col :span="3">
|
||||||
|
<slot name="sidebar"></slot>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="21" :style="{
|
||||||
|
background: '#f0f2f5', padding: '20px', overflow: 'auto',
|
||||||
|
height: 'calc(100vh - 80px)'
|
||||||
|
}">
|
||||||
|
<slot name="content"></slot>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import HomeHeader from "@/containers/HomeHeader.vue"
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
/* .el-menu-vertical-demo:not(.el-menu--collapse) {
|
||||||
|
width: 200px;
|
||||||
|
min-height: 400px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
:global {
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.layout) {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
|
||||||
|
<el-radio-button :label="false">expand</el-radio-button>
|
||||||
|
<el-radio-button :label="true">collapse</el-radio-button>
|
||||||
|
</el-radio-group> -->
|
||||||
|
<div :class="$style['system-menu']">
|
||||||
|
<el-menu :default-active="activeIndex" :default-openeds="openeds" :router="true" class="el-menu-vertical-demo"
|
||||||
|
:collapse="isCollapse" active-text-color="#409eff" background-color="#001529" text-color="#fff"
|
||||||
|
:style="{ border: 0 }" @open="handleOpen" @close="handleClose">
|
||||||
|
<template v-if="menuJson.length == 0">
|
||||||
|
<el-menu-item index="/app/Employee">
|
||||||
|
用戶列表
|
||||||
|
</el-menu-item>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-menu-item v-for="(item, index) in menuJson" :key="item.name" :index="item.route">
|
||||||
|
{{ item.name }}
|
||||||
|
</el-menu-item>
|
||||||
|
</template>
|
||||||
|
</el-menu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onBeforeMount } from 'vue'
|
||||||
|
import {
|
||||||
|
Menu as IconMenu,
|
||||||
|
Setting,
|
||||||
|
} from '@element-plus/icons-vue'
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import * as api from "@/common/api";
|
||||||
|
import { MENU_JSON } from "@/consts/dataDict";
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
menuIdx: string,
|
||||||
|
parentIdxList: string[]
|
||||||
|
}>(), {
|
||||||
|
menuIdx: "/app/system/info",
|
||||||
|
parentIdxList: () => ['system']
|
||||||
|
})
|
||||||
|
|
||||||
|
const activeIndex = ref();
|
||||||
|
const openeds = ref<string[]>([]);
|
||||||
|
const router = useRoute();
|
||||||
|
const menuJson = ref<any>([]);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
activeIndex.value = router.path;
|
||||||
|
switch (true) {
|
||||||
|
case router.path.includes('/app/device'):
|
||||||
|
openeds.value = ['/app/device']
|
||||||
|
break;
|
||||||
|
case router.path.includes('/app/system'):
|
||||||
|
default:
|
||||||
|
openeds.value = ['/app/system/info'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
getMenuJson();
|
||||||
|
})
|
||||||
|
|
||||||
|
const isCollapse = ref(false)
|
||||||
|
const handleOpen = (key: string, keyPath: string[]) => {
|
||||||
|
}
|
||||||
|
const handleClose = (key: string, keyPath: string[]) => {
|
||||||
|
}
|
||||||
|
|
||||||
|
const goTo = (url) => {
|
||||||
|
document.location.href = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMenuJson = async () => {
|
||||||
|
const { data: dataDict } = await api.getDynamic({ id: MENU_JSON }, "dataDict");
|
||||||
|
|
||||||
|
if (dataDict?.value) {
|
||||||
|
try {
|
||||||
|
menuJson.value = JSON.parse(dataDict.value);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style module lang="scss">
|
||||||
|
/* .el-menu-vertical-demo:not(.el-menu--collapse) {
|
||||||
|
width: 200px;
|
||||||
|
min-height: 400px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
:global {
|
||||||
|
:local(.system-menu) {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.el-menu-vertical-demo {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import ExecutionEnvironment from 'exenv';
|
||||||
|
|
||||||
|
function transitionEnd() {
|
||||||
|
const transitionEndEventNames = {
|
||||||
|
WebkitTransition: 'webkitTransitionEnd',
|
||||||
|
MozTransition: 'transitionend',
|
||||||
|
OTransition: 'oTransitionEnd otransitionend',
|
||||||
|
transition: 'transitionend'
|
||||||
|
};
|
||||||
|
if (!ExecutionEnvironment.canUseDOM) {
|
||||||
|
return transitionEndEventNames;
|
||||||
|
}
|
||||||
|
const el = document.createElement('pin');
|
||||||
|
|
||||||
|
for (const name in transitionEndEventNames) {
|
||||||
|
if (el.style[name] !== undefined) {
|
||||||
|
return transitionEndEventNames[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ifHasTransitionEnd = transitionEnd();
|
||||||
|
|
||||||
|
const prefixes = ['Webkit', 'Moz', 'ms', 'O', ''];
|
||||||
|
|
||||||
|
class AnimationManager {
|
||||||
|
constructor() {
|
||||||
|
this.animationHandle = `css${ifHasTransitionEnd ? 3 : 2}Animation`;
|
||||||
|
}
|
||||||
|
|
||||||
|
generate(options) {
|
||||||
|
Object.assign(this, options);
|
||||||
|
return this[this.animationHandle]();
|
||||||
|
}
|
||||||
|
|
||||||
|
css2Animation() {
|
||||||
|
const style = {};
|
||||||
|
style[this.horizontalDirection] = `${this.position[0]}px`;
|
||||||
|
style[this.verticalDirection] = `${this.position[1]}px`;
|
||||||
|
|
||||||
|
this.mixAnimation(style);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
css3Animation() {
|
||||||
|
const style = {};
|
||||||
|
|
||||||
|
prefixes.map(prefix => {
|
||||||
|
let x, y;
|
||||||
|
|
||||||
|
if (this.horizontalDirection === 'right') {
|
||||||
|
x = this.containerWidth - this.size.width - this.position[0];
|
||||||
|
} else {
|
||||||
|
x = this.position[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.verticalDirection === 'bottom') {
|
||||||
|
y = this.containerHeight - this.size.height - this.position[1];
|
||||||
|
} else {
|
||||||
|
y = this.position[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
style[`${prefix}Transform`] = `translate3d(${x}px, ${y}px, 0)`;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.mixAnimation(style);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixAnimation(style) {
|
||||||
|
if (!this.closeAnimation) {
|
||||||
|
prefixes.map(prefix => {
|
||||||
|
style[`${prefix}TransitionDuration`] = `${this.transitionDuration}s`;
|
||||||
|
style[`${prefix}TransitionTimingFunction`] = this.transitionTimingFunction;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnimationManager;
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="container" :class="`${prefixClassName}-container`" :style="containerStyle">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
GridSort
|
||||||
|
} from 'autoresponsive-core3';
|
||||||
|
import pkg from '../../package';
|
||||||
|
import AnimationManager from './animation';
|
||||||
|
import {onBeforeMount, onMounted, onUpdated, ref} from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
containerWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
containerHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
gridWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
prefixClassName: {
|
||||||
|
type: String,
|
||||||
|
default: pkg.name
|
||||||
|
},
|
||||||
|
itemClassName: {
|
||||||
|
type: String,
|
||||||
|
default: 'item'
|
||||||
|
},
|
||||||
|
itemMargin: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
horizontalDirection: {
|
||||||
|
type: String,
|
||||||
|
default: 'left'
|
||||||
|
},
|
||||||
|
transitionDuration: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
transitionTimingFunction: {
|
||||||
|
type: String,
|
||||||
|
default: 'linear'
|
||||||
|
},
|
||||||
|
verticalDirection: {
|
||||||
|
type: String,
|
||||||
|
default: 'top'
|
||||||
|
},
|
||||||
|
closeAnimation: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
onItemDidLayout: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
onContainerDidLayout: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerStyle = {
|
||||||
|
position: 'relative'
|
||||||
|
};
|
||||||
|
|
||||||
|
let animationManager, fixedContainerHeight;
|
||||||
|
onBeforeMount(() => {
|
||||||
|
animationManager = new AnimationManager();
|
||||||
|
fixedContainerHeight = typeof props.containerHeight === 'number';
|
||||||
|
})
|
||||||
|
|
||||||
|
const mixItemInlineStyle = (s) => {
|
||||||
|
const itemMargin = props.itemMargin;
|
||||||
|
let style = {
|
||||||
|
display: 'block',
|
||||||
|
float: 'left',
|
||||||
|
margin: `0 ${itemMargin}px ${itemMargin}px 0`
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.containerWidth) {
|
||||||
|
style = {
|
||||||
|
position: 'absolute'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Object.assign(s, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = ref(null);
|
||||||
|
|
||||||
|
const updateChildren = () => {
|
||||||
|
const sortManager = new GridSort({
|
||||||
|
containerWidth: props.containerWidth,
|
||||||
|
gridWidth: props.gridWidth
|
||||||
|
});
|
||||||
|
sortManager.init();
|
||||||
|
|
||||||
|
let containerHeight = props.verticalDirection === 'bottom' || fixedContainerHeight ? props.containerHeight : 0;
|
||||||
|
|
||||||
|
const children = container.value.children;
|
||||||
|
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
const node = children[i];
|
||||||
|
const canvas = node.__vnode.el;
|
||||||
|
|
||||||
|
let style = {};
|
||||||
|
switch (canvas.style.constructor.name) {
|
||||||
|
case 'CSS2Properties':
|
||||||
|
Object.values(canvas.style).forEach((prop) => {
|
||||||
|
style[prop] = canvas.style[prop];
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'CSSStyleDeclaration':
|
||||||
|
style = canvas.style;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.className &&
|
||||||
|
props.itemClassName &&
|
||||||
|
!~node.className.indexOf(props.itemClassName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const childWidth = parseInt(style.width, 10) + props.itemMargin;
|
||||||
|
const childHeight = parseInt(style.height, 10) + props.itemMargin;
|
||||||
|
const calculatedPosition = sortManager.getPosition(childWidth, childHeight);
|
||||||
|
|
||||||
|
if (fixedContainerHeight) {
|
||||||
|
container.value.style.height = `${containerHeight}px`;
|
||||||
|
} else {
|
||||||
|
if (calculatedPosition[1] + childHeight > containerHeight) {
|
||||||
|
containerHeight = calculatedPosition[1] + childHeight;
|
||||||
|
container.value.style.height = `${containerHeight}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = Object.assign({}, props, {
|
||||||
|
position: calculatedPosition,
|
||||||
|
size: {
|
||||||
|
width: childWidth,
|
||||||
|
height: childHeight
|
||||||
|
},
|
||||||
|
containerHeight: containerHeight
|
||||||
|
});
|
||||||
|
|
||||||
|
const calculatedStyle = animationManager.generate(options);
|
||||||
|
|
||||||
|
mixItemInlineStyle(calculatedStyle);
|
||||||
|
|
||||||
|
Object.assign(node.style, calculatedStyle);
|
||||||
|
|
||||||
|
props.onItemDidLayout(node);
|
||||||
|
|
||||||
|
if (i + 1 === children.length) {
|
||||||
|
props.onContainerDidLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateChildren();
|
||||||
|
})
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
updateChildren();
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// 接口地址
|
||||||
|
export const RECORD_URL = "clyx9ba3a0000qwrb2mjd25sd"
|
||||||
|
// 菜单项
|
||||||
|
export const MENU_JSON = "clyzxul91000mqorb1w503q2o"
|
||||||
|
// 系统名称
|
||||||
|
export const SYSTEM_TITLE = "cm64rpfik0000egrb3x33hbhj"
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['header']">
|
||||||
|
<!-- <img src="/logo.png" height="80"> -->
|
||||||
|
<el-row :style="{ width: '100%' }">
|
||||||
|
<el-col :span="3">
|
||||||
|
<div class="system-name">
|
||||||
|
{{systemTitle||'...'}}
|
||||||
|
<!-- <img src="/logo.png" height="60"> -->
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="21">
|
||||||
|
<div :class="$style['header-content']">
|
||||||
|
<el-dropdown trigger="click" :class="$style['user-panel']">
|
||||||
|
<div ref="userPopup" class="header-user">
|
||||||
|
<span class="name" :style="{ cursor: 'pointer' }">
|
||||||
|
<el-link>
|
||||||
|
{{ appStore.userInfo?.userName }}
|
||||||
|
<el-icon class="el-icon--right">
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
|
</el-link>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item @click="openPwdDialog">更改密码</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click="onLogout">退出登录</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<pwd-dialog ref="pwdRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
import PwdDialog from "@/containers/PwdDialog/index.vue";
|
||||||
|
import { ref, onBeforeMount } from "vue";
|
||||||
|
import {
|
||||||
|
ArrowDown
|
||||||
|
} from "@element-plus/icons-vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { SYSTEM_TITLE } from "@/consts/dataDict";
|
||||||
|
import * as api from "@/common/api";
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const pwdRef = ref<any>();
|
||||||
|
const router=useRouter();
|
||||||
|
const systemTitle = ref();
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const { data: dataDict } = await api.getDynamic({ id: SYSTEM_TITLE }, "dataDict");
|
||||||
|
systemTitle.value = dataDict?.value;
|
||||||
|
}
|
||||||
|
)();
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
const userInfo = Cookies.get("UserInfo");
|
||||||
|
try {
|
||||||
|
const uI = JSON.parse(userInfo);
|
||||||
|
if (!uI?.id) {
|
||||||
|
router.push("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appStore.saveUserInfo(uI);
|
||||||
|
} catch (error) {
|
||||||
|
router.push("/login");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const onLogout = () => {
|
||||||
|
Cookies.remove("Authorization")
|
||||||
|
window.location.href = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*/
|
||||||
|
const openPwdDialog = () => {
|
||||||
|
pwdRef.value?.show();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.header) {
|
||||||
|
height: 80px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.system-name {
|
||||||
|
height: 80px;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 80px;
|
||||||
|
background: #002140;
|
||||||
|
// display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 20px;
|
||||||
|
width: 100%;
|
||||||
|
line-height: 80px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.header-content) {
|
||||||
|
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
|
||||||
|
height: 80px; // calc(100% - 4px);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
:local(.user-panel) {
|
||||||
|
position: absolute;
|
||||||
|
right: 40px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="style" :class="$style['image-cell']" @click="$emit('show', id)">
|
||||||
|
<div :class="$style['img-container']">
|
||||||
|
<div class="img-box">
|
||||||
|
<img :src="src">
|
||||||
|
<div class="footer">
|
||||||
|
<div>
|
||||||
|
<div>时间:{{ fDT(info?.time) }}</div>
|
||||||
|
<div>置信度:{{ toFixed((info?.confidence || 0) / 100) }}</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>类型:{{ getObjectTypeName(info?.objectType) }}</div>
|
||||||
|
<div>地点:{{ info?.deviceName || '--' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { toFixed, getObjectTypeName } from "@/common/tool"
|
||||||
|
import { fDT } from "funjialib";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: any,
|
||||||
|
src: string,
|
||||||
|
confidence: any,
|
||||||
|
info: any,
|
||||||
|
style: any
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(n: 'show', id: any): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.image-cell) {
|
||||||
|
:local(.img-container) {
|
||||||
|
padding: 0 10px 10px 10px;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
height: calc(100% - 40px);
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
background-color: #d3d3d3;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
object-fit: contain;
|
||||||
|
height: calc(100% - 40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
width: 100px;
|
||||||
|
// border: 2px solid #989898;
|
||||||
|
color: #000;
|
||||||
|
border: 0;
|
||||||
|
// border-left-width: 6px;
|
||||||
|
height: 50px;
|
||||||
|
width: 100%; //calc(100% - 8px);
|
||||||
|
// line-height: 36px;
|
||||||
|
padding-left: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: #FFF;
|
||||||
|
|
||||||
|
&>div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['image-list']">
|
||||||
|
<fixed-size-grid :key="gridKey" :columnCount="columnCount" :columnWidth="304" :height="containerHeight || 600"
|
||||||
|
:rowCount="rowCount" :rowHeight="240" :width="1560">
|
||||||
|
<template v-slot:default="slotProps">
|
||||||
|
<image-cell v-if="isShowColumn(slotProps)" :key="getData(slotProps)?.id || slotProps.key"
|
||||||
|
:style="slotProps.style" :id="getData(slotProps)?.id" :src="getData(slotProps)?.objectUrl"
|
||||||
|
:confidence="getData(slotProps)?.confidence" :info="{ ...getData(slotProps) }"
|
||||||
|
@show="(id) => $emit('show', id)">
|
||||||
|
</image-cell>
|
||||||
|
</template>
|
||||||
|
</fixed-size-grid>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { FixedSizeGrid } from '@kousum/vue3-window';
|
||||||
|
import ImageCell from "./ImageCell.vue";
|
||||||
|
import { watch, ref, computed } from "vue";
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{ data: any[], containerHeight: number }>(), {
|
||||||
|
containerHeight: 600
|
||||||
|
});
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(n: 'show', id: any): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
|
||||||
|
const gridKey = ref(-1);
|
||||||
|
const columnCount = ref(5);
|
||||||
|
|
||||||
|
watch(() => props.data, (v) => {
|
||||||
|
gridKey.value = new Date().getTime();
|
||||||
|
})
|
||||||
|
|
||||||
|
const rowCount = computed(() => {
|
||||||
|
const len = props.data?.length || 0;
|
||||||
|
let _rowCount = len / columnCount.value;
|
||||||
|
if (len % columnCount.value) {
|
||||||
|
_rowCount += 1;
|
||||||
|
}
|
||||||
|
return _rowCount;
|
||||||
|
})
|
||||||
|
|
||||||
|
const getData = (prop) => {
|
||||||
|
return props.data?.[prop.rowIndex * columnCount.value + prop.columnIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
const isShowColumn = (prop) => {
|
||||||
|
return (props.data?.length || 0) > prop.rowIndex * columnCount.value + prop.columnIndex;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.image-list) {
|
||||||
|
width: 1400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<el-form ref="formRef" label-width="80px" :model="formModel" :rules="rules">
|
||||||
|
<el-form-item label="用户名">
|
||||||
|
<span>{{ appStore.userinfo.userName }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="原密码" prop="oldPassword">
|
||||||
|
<el-input placeholder="请输入" show-password v-model="formModel.oldPassword" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码" prop="newPassword">
|
||||||
|
<el-input placeholder="6-18个字母,区分大小写" show-password v-model="formModel.newPassword" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认密码" prop="newPassword2">
|
||||||
|
<el-input placeholder="请再次输入密码" show-password v-model="formModel.newPassword2" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export interface PwdFormRefProps {
|
||||||
|
submit: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormDataProps {
|
||||||
|
oldPassword: string;
|
||||||
|
newPassword: string;
|
||||||
|
newPassword2: string;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref } from "vue";
|
||||||
|
import type { FormItemRule } from "element-plus";
|
||||||
|
import { useAppStore } from "@/store";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* emit
|
||||||
|
*/
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "onLoading", v: boolean): void;
|
||||||
|
(e: "onSuccess"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const formRef = ref();
|
||||||
|
const formModel = reactive<FormDataProps>({
|
||||||
|
oldPassword: "",
|
||||||
|
newPassword: "",
|
||||||
|
newPassword2: "",
|
||||||
|
});
|
||||||
|
const rules = ref<Record<string, FormItemRule | FormItemRule[]>>({
|
||||||
|
oldPassword: {
|
||||||
|
required: true,
|
||||||
|
message: "请输入原密码",
|
||||||
|
},
|
||||||
|
newPassword: {
|
||||||
|
required: true,
|
||||||
|
message: "请输入新密码",
|
||||||
|
},
|
||||||
|
newPassword2: {
|
||||||
|
required: true,
|
||||||
|
message: "请确认新密码",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*/
|
||||||
|
const onUpdate = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
emit("onLoading", false);
|
||||||
|
emit("onSuccess");
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交表单
|
||||||
|
*/
|
||||||
|
const onSubmit = () => {
|
||||||
|
formRef.value.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
emit("onLoading", true);
|
||||||
|
onUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暴露给父组件
|
||||||
|
*/
|
||||||
|
defineExpose({
|
||||||
|
submit: onSubmit,
|
||||||
|
} as PwdFormRefProps);
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<um-dialog v-model="visible" title="修改密码" width="328px" :footer="false">
|
||||||
|
<um-table-form :target="UpdatePassword" :data="formData" @ok="onResetSubmit" @cancel="onResetCancel">
|
||||||
|
</um-table-form>
|
||||||
|
</um-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export interface PwdDialogRefProps {
|
||||||
|
/**
|
||||||
|
* 打开弹窗
|
||||||
|
*/
|
||||||
|
show: () => void;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import PwdForm, { PwdFormRefProps } from "./PwdForm.vue";
|
||||||
|
import { UmTableForm,UmDialog } from "funjiaui";
|
||||||
|
import { UpdatePassword } from "@/containers/viewModel/UpdatePassword";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
import * as api from "@/common/api";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import md5 from "md5";
|
||||||
|
import { encode } from "@/common/tool"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* emit
|
||||||
|
*/
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "onSuccess"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
|
const formRef = ref<PwdFormRefProps>();
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
const app = useAppStore();
|
||||||
|
const formData = ref<any>({
|
||||||
|
userName: app.userInfo?.userName,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改loading状态
|
||||||
|
*/
|
||||||
|
const onLoading = (v: boolean) => {
|
||||||
|
loading.value = v;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单操作成功
|
||||||
|
*/
|
||||||
|
const onSuccess = () => {
|
||||||
|
visible.value = false;
|
||||||
|
loading.value = false;
|
||||||
|
emit("onSuccess");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交表单
|
||||||
|
*/
|
||||||
|
const onOk = () => {
|
||||||
|
formRef.value?.submit();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onResetSubmit = async (formData: any) => {
|
||||||
|
const params = {
|
||||||
|
old_password: md5(formData.oldPassword),
|
||||||
|
new_password: encode(formData.password),
|
||||||
|
};
|
||||||
|
|
||||||
|
const { status, reason } = await api.udpdatePwd(params);
|
||||||
|
if (status != "200") {
|
||||||
|
ElMessage.error(reason || "修改失败");
|
||||||
|
} else {
|
||||||
|
ElMessage.success("修改密码成功,3秒内将退出登录");
|
||||||
|
setTimeout(() => {
|
||||||
|
router.push("/login");
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onResetCancel = (value: boolean) => {
|
||||||
|
visible.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暴露给父组件
|
||||||
|
*/
|
||||||
|
defineExpose({
|
||||||
|
show: () => {
|
||||||
|
visible.value = true;
|
||||||
|
},
|
||||||
|
} as PwdDialogRefProps);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import { UmTableForm,
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "@/common/api"
|
||||||
|
// 数据字典
|
||||||
|
const tableName = "dataDict";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 数据字典
|
||||||
|
export default class DataDict {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "数据", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "唯一标识", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "唯一标识", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
unionKey: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "数据", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "数据", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
value: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "描述", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "描述", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
desc: string = ""
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getDynamicList(params, tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addDynamic({ ...data, unionKey: data.unionKey.toUpperCase() }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getDynamic({ id: rowId }, tableName);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateDynamic({ ...params, unionKey: params.unionKey.toUpperCase() }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids: [rowId] }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:toolbar", "value": { "type": "批量删除", "priority": 5, "es": "onAfter", "dialogContent": "确定要删除选择的数据吗?" } })
|
||||||
|
onMutilDel = async (ids: any[]) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exportText(filename, text) {
|
||||||
|
var element = document.createElement('a');
|
||||||
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
|
||||||
|
element.setAttribute('download', filename);
|
||||||
|
|
||||||
|
element.style.display = 'none';
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
element.click();
|
||||||
|
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "自定义", id: "anki", "priority": 1, "es": "onAfter", title: "导出字典常量表"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onExport = async (params: any) => {
|
||||||
|
const { data } = await api.getDynamicList({ ...params, page: 1, pageSize: 10000 }, tableName);
|
||||||
|
|
||||||
|
const content = data.map(item => {
|
||||||
|
return `export const ${item.unionKey} = "${item.id}"`;
|
||||||
|
}).join("\n")
|
||||||
|
|
||||||
|
this.exportText("dataDict.ts", content);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "@/common/api"
|
||||||
|
|
||||||
|
|
||||||
|
export default class Employee {
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "姓名", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "姓名", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
name: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "用戶名", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "用戶名", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
userName: string = "";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "密码", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
pwd: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "手机号", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "手机号", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
phone: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "车牌号码", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "车牌号码", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
vehiclePlateNumber: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "用户信息图片地址", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "用户信息图片地址", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
userInfoPic: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "通知总数", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "通知总数", fieldType: "number", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
noticeTotal: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "备注", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "备注" })
|
||||||
|
remark: string = "";
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getEmployeeList(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @tcmd({
|
||||||
|
// "key": "table:toolbar", "value": {
|
||||||
|
// "type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// onAdd = async (data: any) => {
|
||||||
|
// const { code, msg } = await api.addEmployee(data);
|
||||||
|
// if (code != 0) {
|
||||||
|
// return { code: 1, message: msg };
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return { code: 0 };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getEmployee({ id: rowId });
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
params.source_type = "IPC";
|
||||||
|
params.forever = true;
|
||||||
|
|
||||||
|
const { code, msg } = await api.updateEmployee(params);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @tcmd({
|
||||||
|
// "value": {
|
||||||
|
// "type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
// sort: 3,
|
||||||
|
// // isShow
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// delByIds = async (rowId: number) => {
|
||||||
|
// const { code, msg } = await api.deleteEmployee({ ids: [rowId] });
|
||||||
|
// if (code != 0) {
|
||||||
|
// return { code: 1, message: msg };
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return { code: 0 };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "@/common/api"
|
||||||
|
// import { ElMessage } from 'element-plus'
|
||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Notice {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "消息", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "消息", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
message: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "排序", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "排序", fieldType: "number", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
sort: number = 1;
|
||||||
|
|
||||||
|
static userId: any;
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getNoticeList(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addNotice({ ...data, userId: Notice.userId });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getNotice({ id: rowId });
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateNotice({ ...params, userId: Notice.userId });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteNotice({ ids: [rowId] });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @tcmd({
|
||||||
|
// "value": {
|
||||||
|
// "id": 1, "type": "customOperateEvent", "title": "详情",
|
||||||
|
// sort: 1,
|
||||||
|
// isShow: (rowData) => {
|
||||||
|
// if (rowData?.snaper_image > 0) {
|
||||||
|
// return true;
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// jumpEmployee = (rowId: number) => {
|
||||||
|
// return rowId;
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "@/common/api"
|
||||||
|
import { h, ref } from 'vue';
|
||||||
|
import SingleUpload from '@/components/SingleUpload.vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
// 插件模块
|
||||||
|
const tableName = "plugin";
|
||||||
|
|
||||||
|
const isShow = (rowData: any) => {
|
||||||
|
if (rowData?.source_add_type == "1") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Plugin2 {
|
||||||
|
// 侵入性事件注入
|
||||||
|
static singleListen: any = null
|
||||||
|
|
||||||
|
static isEdit = false;
|
||||||
|
|
||||||
|
// 操作列宽度
|
||||||
|
static operateWidth = "140px";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
questionId: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "名称", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "名称", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
name: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "描述", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "描述", fieldType: "string", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
desc: string = ""
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "插件脚本绝对地址", minWidth: 120 })
|
||||||
|
@tfcpd({
|
||||||
|
"lang": "", "def": "插件脚本绝对地址", component: function (props) {
|
||||||
|
const value = ref<any>();
|
||||||
|
const that = this;
|
||||||
|
return h(SingleUpload, {
|
||||||
|
modelValue: value,
|
||||||
|
"onFileChange": async (data) => {
|
||||||
|
const fdata = new FormData();
|
||||||
|
fdata.append("file", data);
|
||||||
|
const res = await axios.post('/api/upload/file', fdata);
|
||||||
|
value.value = res.data?.url
|
||||||
|
// this.$emit("");
|
||||||
|
// debugger;
|
||||||
|
// console.log(res.data?.url,props);
|
||||||
|
props['onUpdate:modelValue']?.(res.data?.url);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
rule: [{ "type": "require", message: "不能为空" }]
|
||||||
|
})
|
||||||
|
pluginUrl: string = ""
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getDynamicList(params, tableName);
|
||||||
|
// return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addDynamic({ ...data }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑" } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getDynamic({ id: rowId }, tableName);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateDynamic({ ...params }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids: [rowId] }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:toolbar", "value": { "type": "批量删除", "priority": 5, "es": "onAfter", "dialogContent": "确定要删除选择的数据吗?" } })
|
||||||
|
onMutilDel = async (ids: any[]) => {
|
||||||
|
const { code, msg } = await api.deleteDynamic({ ids }, tableName);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
import 'reflect-metadata';
|
||||||
|
// import {
|
||||||
|
// TableColumnPropertyDecorator as tcpd,
|
||||||
|
// TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
// TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
// TableSearchFormPropertyDecorator as tsfpd
|
||||||
|
// } from "@/components/UmTable";
|
||||||
|
import * as api from "@/common/api"
|
||||||
|
// import UmTableForm from '@/components/UmTable/UmTableForm.vue';
|
||||||
|
|
||||||
|
import { UmTableForm,
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd
|
||||||
|
} from "funjiaui";
|
||||||
|
// import {
|
||||||
|
// TableColumnPropertyDecorator as tcpd,
|
||||||
|
// TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
// TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
// TableSearchFormPropertyDecorator as tsfpd
|
||||||
|
// } from "funjiaui/UmTable";
|
||||||
|
|
||||||
|
|
||||||
|
import DynamicTags from '@/components/DynamicTags.vue';
|
||||||
|
// import { ElButton, ElInput, ElTag,ElDialog } from 'element-plus';
|
||||||
|
import { Codemirror } from 'vue-codemirror';
|
||||||
|
|
||||||
|
|
||||||
|
export default class QA {
|
||||||
|
@tcpd({ "lang": "", "def": "id", width: 240 })
|
||||||
|
@tfcpd({ "lang": "", "def": "id", fieldType: "primaryKey" })
|
||||||
|
id: number = 0;
|
||||||
|
|
||||||
|
@tsfpd({ lang: "", "def": "题目" })
|
||||||
|
@tcpd({ "lang": "", "def": "题目", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "题目", rule: [{ "type": "require", message: "不能为空" }], component: Codemirror })
|
||||||
|
question: string = "";
|
||||||
|
|
||||||
|
// @tcpd({ "lang": "", "def": "答案", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "答案", component: Codemirror, width: 300 })
|
||||||
|
answer: string = "";
|
||||||
|
|
||||||
|
@tcpd({ "lang": "", "def": "标签", minWidth: 120 })
|
||||||
|
@tfcpd({ "lang": "", "def": "标签", component: DynamicTags, width: 300 })
|
||||||
|
@tsfpd({
|
||||||
|
lang: "", "def": "标签", fieldType: "select", async getData() {
|
||||||
|
return {
|
||||||
|
data: [{
|
||||||
|
label: "vue3",
|
||||||
|
value: "vue3"
|
||||||
|
}, {
|
||||||
|
label: "react",
|
||||||
|
value: "react"
|
||||||
|
}, {
|
||||||
|
label: "js",
|
||||||
|
value: "js"
|
||||||
|
}, {
|
||||||
|
label: "html",
|
||||||
|
value: "html"
|
||||||
|
}, {
|
||||||
|
label: "css",
|
||||||
|
value: "css"
|
||||||
|
}, {
|
||||||
|
label: "webpack",
|
||||||
|
value: "webpack"
|
||||||
|
}, {
|
||||||
|
label: "微信小程序",
|
||||||
|
value: "微信小程序"
|
||||||
|
}, {
|
||||||
|
label: "typescript",
|
||||||
|
value: "typescript"
|
||||||
|
}, {
|
||||||
|
label: "boss_vue",
|
||||||
|
value: "boss_vue"
|
||||||
|
}, {
|
||||||
|
label: "高频_css",
|
||||||
|
value: "高频_css"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
tag: string[] = [];
|
||||||
|
|
||||||
|
@tcmd({ "key": "table:searchFormMethod", "value": { "type": "getList", "es": "onAfter" } })
|
||||||
|
getList = async (params: any) => {
|
||||||
|
return await api.getQAList(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 1200
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onAdd = async (data: any) => {
|
||||||
|
const { code, msg } = await api.addQA({ ...data });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exportText(filename, text) {
|
||||||
|
var element = document.createElement('a');
|
||||||
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
|
||||||
|
element.setAttribute('download', filename);
|
||||||
|
|
||||||
|
element.style.display = 'none';
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
element.click();
|
||||||
|
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"key": "table:toolbar", "value": {
|
||||||
|
"type": "自定义", "priority": 1, "es": "onAfter", title: "导出anki脚本"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onExport = async (params: any) => {
|
||||||
|
const { data } = await api.getQAList({ ...params, page: 1, pageSize: 10000 });
|
||||||
|
const head = `#separator:tab
|
||||||
|
#html:true
|
||||||
|
#tags column:3
|
||||||
|
`
|
||||||
|
const style = `<style>iframe{width:100%;height:90vh;}</style>`;
|
||||||
|
|
||||||
|
const content = data.map(item => {
|
||||||
|
return `"${style}<iframe src=""http://192.168.6.130:5176/#/question?id=${item.id}"" frameborder=""0""></iframe><br>" "${style}<iframe src=""http://192.168.6.130:5176/#/answer?id=${item.id}"" frameborder=""0""></iframe><br>"`;
|
||||||
|
}).join("\n")
|
||||||
|
|
||||||
|
this.exportText("anki脚本.txt", head + content);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑", "dialogWidth": 1200 } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getQA({ id: rowId });
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateQA({ ...params });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
sort: 3,
|
||||||
|
dialogWidth: 400
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
delByIds = async (rowId: number) => {
|
||||||
|
const { code, msg } = await api.deleteQA({ ids: [rowId] });
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @tcmd({
|
||||||
|
// "key": "table:toolbar", "value": {
|
||||||
|
// "type": "添加", "priority": 1, "es": "onAfter", "dialogContent": UmTableForm, "dialogTitle": "增加", "dialogWidth": 650
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// onAdd = async (data: any) => {
|
||||||
|
// const { code, msg } = await api.addQA(data);
|
||||||
|
// if (code != 0) {
|
||||||
|
// return { code: 1, message: msg };
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return { code: 0 };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取详情数据
|
||||||
|
*/
|
||||||
|
@tcmd({ "value": { "type": "edit", "es": "onBefore", "dialogContent": UmTableForm, "dialogTitle": "编辑", dialogWidth: 1200 } })
|
||||||
|
getDetail = async (rowId: number, r, meta) => {
|
||||||
|
const { data } = await api.getQA({ id: rowId });
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@tcmd({
|
||||||
|
"value": {
|
||||||
|
"type": "edit", "es": "onAfter",
|
||||||
|
sort: 2,
|
||||||
|
// isShow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onEdit = async (params: any) => {
|
||||||
|
const { code, msg } = await api.updateQA(params);
|
||||||
|
if (code != 0) {
|
||||||
|
return { code: 1, message: msg };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { code: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @tcmd({
|
||||||
|
// "value": {
|
||||||
|
// "type": "del", "es": "onAfter", "dialogContent": "确定要删除该条数据吗?",
|
||||||
|
// sort: 3,
|
||||||
|
// // isShow
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// delByIds = async (rowId: number) => {
|
||||||
|
// const { code, msg } = await api.deleteQA({ ids: [rowId] });
|
||||||
|
// if (code != 0) {
|
||||||
|
// return { code: 1, message: msg };
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return { code: 0 };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
import 'reflect-metadata';
|
||||||
|
import {
|
||||||
|
TableColumnPropertyDecorator as tcpd,
|
||||||
|
TableFormColumnPropertyDecorator as tfcpd,
|
||||||
|
TableColumnMethodDecorator as tcmd, TOperateType,
|
||||||
|
TableSearchFormPropertyDecorator as tsfpd,
|
||||||
|
UmTableForm
|
||||||
|
} from "funjiaui";
|
||||||
|
import * as api from "@/common/api"
|
||||||
|
// import UmTableForm from '@/components/UmTable/UmTableForm.vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*/
|
||||||
|
export class UpdatePassword {
|
||||||
|
@tfcpd({ "lang": "", "def": "编号", "fieldType": "primaryKey" })
|
||||||
|
id: number | string = 0;
|
||||||
|
|
||||||
|
// @tcpd({ lang: "name", def: "账号名称" })
|
||||||
|
// @tfcpd({
|
||||||
|
// "lang": "", "def": "账号名称", "fieldType": "default", rule: [{ "type": "require", message: "不能为空" }],
|
||||||
|
// disabled: true
|
||||||
|
// })
|
||||||
|
// userName: string = "";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "原密码", "fieldType": "password", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
oldPassword: string = "";
|
||||||
|
|
||||||
|
@tfcpd({ "lang": "", "def": "新密码", "fieldType": "password", rule: [{ "type": "require", message: "不能为空" }] })
|
||||||
|
password: string = "";
|
||||||
|
|
||||||
|
@tfcpd({
|
||||||
|
"lang": "", "def": "确认密码", "fieldType": "password", rule: [{
|
||||||
|
"type": "require", message: "不能为空",
|
||||||
|
}, {
|
||||||
|
"type": "validator",
|
||||||
|
validator: function (rule: any, value: any, callback: any) {
|
||||||
|
const that: any = this;
|
||||||
|
if (value != that.formData["password"]) {
|
||||||
|
return new Error("两次输入的密码不对");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
passwordConfirm: string = "";
|
||||||
|
}
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue-cropperjs';
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from "@/router";
|
||||||
|
import { createPinia } from "pinia";
|
||||||
|
import "./assets/icon/iconfont.css";
|
||||||
|
|
||||||
|
const app = createApp(App);
|
||||||
|
app.use(router);
|
||||||
|
app.use(createPinia());
|
||||||
|
app.mount('#app')
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
|
||||||
|
import Employee from "@/views/Employee.vue";
|
||||||
|
import Notice from "@/views/Notice.vue";
|
||||||
|
import QA from "@/views/QA.vue";
|
||||||
|
import DataDict from "@/views/DataDict.vue";
|
||||||
|
import DynamicTable from "@/views/DynamicTable.vue";
|
||||||
|
import Plugin from "@/views/Plugin.vue";
|
||||||
|
|
||||||
|
const routes: Array<RouteRecordRaw | any> = [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
component: () => import("@/views/Login.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/login",
|
||||||
|
component: () => import("@/views/Login.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/app",
|
||||||
|
component: () => import("@/components/Layout.vue"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: Employee,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/app/Employee",
|
||||||
|
component: Employee,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/app/Notice",
|
||||||
|
component: Notice,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/app/QA",
|
||||||
|
component: QA,
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// path: "/app/tag",
|
||||||
|
// component: Tag,
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
path: "/app/dynamicTable/:name/:path/:title?",
|
||||||
|
// component: Record,
|
||||||
|
component: DynamicTable,
|
||||||
|
// 动态表格
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/app/dataDict",
|
||||||
|
component: DataDict,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/app/plugin",
|
||||||
|
component: Plugin,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// path: "/:pathMatch(.*)*",
|
||||||
|
// component: () => import("@/views/NotFound/index.vue"),
|
||||||
|
// },
|
||||||
|
];
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHashHistory(),
|
||||||
|
routes,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
interface AppType {
|
||||||
|
userInfo: any;
|
||||||
|
isMiniMenu: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAppStore = defineStore("app", {
|
||||||
|
state: (): AppType => ({
|
||||||
|
userInfo: {},
|
||||||
|
isMiniMenu: false
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
/**
|
||||||
|
* 保存登录者信息
|
||||||
|
*/
|
||||||
|
saveUserInfo(payload: any) {
|
||||||
|
this.userInfo = payload;
|
||||||
|
},
|
||||||
|
removeUserInfo() {
|
||||||
|
this.userInfo = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/** 图片预览图片索引切换类型值 */
|
||||||
|
declare type TImgPreviewIdx = -1 | 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片类型
|
||||||
|
* 图片类型, 0:人脸, 1:自行车, 2:巴士, 3:小汽车, 4:电动车|摩托车, 5:人体, 6:三轮车,7货车、8车牌、9推车,10鸟、11猫,12 狗,13老鼠
|
||||||
|
* "0 face","1 bicycle","2 bus","3 car","4 motorbike","5 person","6 tricycle","7 truck","8 carplate","9 pram","10 bird","11 cat", "12 dog", "13 mouse"
|
||||||
|
*/
|
||||||
|
declare type TObjectType = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单状态
|
||||||
|
* 0:待完成 1:已完成 2:已取消
|
||||||
|
*/
|
||||||
|
declare type TStatus = 0 | 1 | 2;
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['device-list']">
|
||||||
|
<h2>数据字典列表</h2>
|
||||||
|
<um-table-class-enhance class="role-right" :target="Record" :data="[]"
|
||||||
|
:other-params="{ userId: appStore.userInfo?.id }" @data-change="onDataChange"
|
||||||
|
@fire="onFire">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
// import UmTableClassEnhance from "@/components/UmTable/UmByClassEnhance.vue";
|
||||||
|
import { UmByClassEnhance as UmTableClassEnhance } from "funjiaui";
|
||||||
|
import Record from "@/containers/viewModel/DataDict";
|
||||||
|
import ImgPreview from "@/components/ImgPreview.vue";
|
||||||
|
import { ref, reactive, watch } from "vue";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const imgIndex = ref(0);
|
||||||
|
const ipcImgList = ref([]);
|
||||||
|
const imgPreviewInfo = reactive({
|
||||||
|
id: "",
|
||||||
|
imgUrl: "",
|
||||||
|
position: "",
|
||||||
|
time: "",
|
||||||
|
deviceName: ""
|
||||||
|
});
|
||||||
|
const currentDeviceId = ref(null);
|
||||||
|
const appStore = useAppStore();
|
||||||
|
// const formData = reactive<Notice>(traveInfomation)
|
||||||
|
|
||||||
|
|
||||||
|
const onDataChange = (data) => {
|
||||||
|
// ipcImgList.value = data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFire = async (key: string, value, data: any) => {
|
||||||
|
// imgIndex.value = 0;
|
||||||
|
// const resData = await api.getCaputreImgListByIpcId({ id: data })
|
||||||
|
// ipcImgList.value = resData.data?.objectList || [];
|
||||||
|
// initImgPreviewInfo(ipcImgList.value?.[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.device-list) {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.img-preview-dialog) {
|
||||||
|
:local(.footer) {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['device-list']">
|
||||||
|
<h2>{{ router.params?.title || router.params?.name }}</h2>
|
||||||
|
<um-table-class-enhance v-if="obj" class="role-right" :target="obj" :data="[]"
|
||||||
|
:other-params="{ userId: appStore.userInfo?.id }" @data-change="onDataChange" @fire="onFire">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
// import UmTableClassEnhance from "@/components/UmTable/UmByClassEnhance.vue";
|
||||||
|
import { UmByClassEnhance as UmTableClassEnhance } from "funjiaui";
|
||||||
|
// import UmDialog from "@/components/UmDialog/index.vue";
|
||||||
|
// import RecordUser from "@/containers/viewModel/RecordUser";
|
||||||
|
// import ImgPreview from "@/components/ImgPreview.vue";
|
||||||
|
import { ref, reactive, watch, onMounted } from "vue";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
// import ThirdPartyLoader from "@/common/ThirdPartyLoader"
|
||||||
|
import { useRoute, onBeforeRouteUpdate } from "vue-router";
|
||||||
|
|
||||||
|
// async function loadModuleFromUrl(url) {
|
||||||
|
// const response = await fetch(url);
|
||||||
|
// const moduleCode = await response.text();
|
||||||
|
|
||||||
|
// // 创建一个新的模块
|
||||||
|
// const module = new Function('module', 'exports', moduleCode);
|
||||||
|
|
||||||
|
// // 执行模块
|
||||||
|
// const exports = {};
|
||||||
|
// module({ exports });
|
||||||
|
|
||||||
|
// return exports;
|
||||||
|
// }
|
||||||
|
|
||||||
|
class ThirdPartyLoader {
|
||||||
|
loadedModules: any = {};
|
||||||
|
constructor() {
|
||||||
|
this.loadedModules = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
loadModule(moduleName, url) {
|
||||||
|
if (!this.loadedModules[moduleName]) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = url;
|
||||||
|
script.onload = () => {
|
||||||
|
this.loadedModules[moduleName] = true;
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
script.onerror = (error) => {
|
||||||
|
reject(error);
|
||||||
|
};
|
||||||
|
document.body.appendChild(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const imgIndex = ref(0);
|
||||||
|
const ipcImgList = ref([]);
|
||||||
|
const imgPreviewInfo = reactive({
|
||||||
|
id: "",
|
||||||
|
imgUrl: "",
|
||||||
|
position: "",
|
||||||
|
time: "",
|
||||||
|
deviceName: ""
|
||||||
|
});
|
||||||
|
const currentDeviceId = ref(null);
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const obj = ref(null);
|
||||||
|
const router = useRoute();
|
||||||
|
|
||||||
|
// const formData = reactive<Notice>(traveInfomation)
|
||||||
|
|
||||||
|
function capitalizeFirstLetter(str) {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const { name, path } = router.params;
|
||||||
|
await new ThirdPartyLoader().loadModule(name, "/static/" + path + ".js")
|
||||||
|
// console.log(window[capitalizeFirstLetter(name)]);
|
||||||
|
obj.value = window[capitalizeFirstLetter(name)];
|
||||||
|
// 使用示例
|
||||||
|
// loadModuleFromUrl('/box-admin.iife.js').then(module => {
|
||||||
|
// // 在这里使用导入的模块
|
||||||
|
// // const t=new module;
|
||||||
|
// console.log(module);
|
||||||
|
// });
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => router.params.name, async () => {
|
||||||
|
const { name, path } = router.params;
|
||||||
|
await new ThirdPartyLoader().loadModule(name, "/static/" + path + ".js")
|
||||||
|
// console.log(window[capitalizeFirstLetter(name)]);
|
||||||
|
obj.value = window[capitalizeFirstLetter(name)];
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
onBeforeRouteUpdate((to, from) => {
|
||||||
|
// 在此处执行刷新相关的操作
|
||||||
|
// debugger;
|
||||||
|
});
|
||||||
|
|
||||||
|
const onDataChange = (data) => {
|
||||||
|
// ipcImgList.value = data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFire = async (key: string, value, data: any) => {
|
||||||
|
// imgIndex.value = 0;
|
||||||
|
// const resData = await api.getCaputreImgListByIpcId({ id: data })
|
||||||
|
// ipcImgList.value = resData.data?.objectList || [];
|
||||||
|
// initImgPreviewInfo(ipcImgList.value?.[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.device-list) {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.img-preview-dialog) {
|
||||||
|
:local(.footer) {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['device-list']">
|
||||||
|
<h2>用戶列表</h2>
|
||||||
|
<um-table-class-enhance class="role-right" :target="Employee" :data="[]" @data-change="onDataChange" @fire="onFire">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UmByClassEnhance as UmTableClassEnhance,UmDialog } from "funjiaui";
|
||||||
|
import Employee from "@/containers/viewModel/Employee";
|
||||||
|
import { ref, reactive, watch } from "vue";
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
const onDataChange = (data) => {
|
||||||
|
// ipcImgList.value = data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFire = async (key: string, value, data: any) => {
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.device-list) {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['login']">
|
||||||
|
<div class="login-form">
|
||||||
|
<!-- <img src="/logo.png" :style="{ marginLeft: '45px', marginBottom: '20px' }"> -->
|
||||||
|
<h1>{{systemTitle||'...'}}</h1>
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules">
|
||||||
|
<el-form-item prop="user">
|
||||||
|
<el-input placeholder="请输入用户名" :prefix-icon="User" size="large" v-model.trim="form.user" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input placeholder="请输入密码" :prefix-icon="Lock" show-password size="large"
|
||||||
|
v-model.trim="form.password" @keyup.enter="onSubmit" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button class="login-btn" :loading="loading" round size="large" type="primary" @click="onSubmit">
|
||||||
|
登 录
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, onBeforeMount, onBeforeUnmount, computed } from "vue";
|
||||||
|
import { ElMessage, FormItemRule } from "element-plus";
|
||||||
|
import * as api from "@/common/api";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { User, Lock } from "@element-plus/icons-vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
import { SYSTEM_TITLE } from "@/consts/dataDict";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const formRef = ref();
|
||||||
|
const form = reactive({
|
||||||
|
user: "",
|
||||||
|
password: ""
|
||||||
|
});
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const systemTitle = ref();
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const { data: dataDict } = await api.getDynamic({ id: SYSTEM_TITLE }, "dataDict");
|
||||||
|
systemTitle.value = dataDict?.value;
|
||||||
|
}
|
||||||
|
)();
|
||||||
|
|
||||||
|
const rules = ref<Record<string, FormItemRule | FormItemRule[]>>({
|
||||||
|
user: {
|
||||||
|
required: true,
|
||||||
|
message: "请输入用户名",
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
required: true,
|
||||||
|
message: "请输入密码",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
formRef.value?.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
const { code, data } = await api.employeeLogin({
|
||||||
|
userName: form.user,
|
||||||
|
pwd: form.password
|
||||||
|
});
|
||||||
|
|
||||||
|
if (code == 0 && data) {
|
||||||
|
// 保存登录token信息并设置cookie 过期时间为3天
|
||||||
|
// Cookies.set("Authorization", token, { expires: 3 });
|
||||||
|
Cookies.set("UserInfo", JSON.stringify(data), { expires: 3 });
|
||||||
|
|
||||||
|
appStore.saveUserInfo(data);
|
||||||
|
router.push("/app");
|
||||||
|
// router.push("/app/system/info");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ElMessage.error("登录失败");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.login) {
|
||||||
|
background-image: url(/login_bg.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
width: 400px;
|
||||||
|
height: 400px;
|
||||||
|
// padding: 120px 160px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 1px;
|
||||||
|
left: 1px;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
.el-input__wrapper {
|
||||||
|
background-color: transparent;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: #FFFF;
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 234px;
|
||||||
|
margin: 0px auto 30px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input {
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
.el-input__inner {
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__inner) {
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-btn {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 30px;
|
||||||
|
background: linear-gradient(180deg, #039ad0 0%, #0250bc 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['device-list']">
|
||||||
|
<h2>通知列表</h2>
|
||||||
|
<um-table-class-enhance class="role-right" :target="Notice" :data="[]"
|
||||||
|
:other-params="{ userId: appStore.userInfo?.id }" @data-change="onDataChange"
|
||||||
|
@fire="onFire">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
// import UmTableClassEnhance from "@/components/UmTable/UmByClassEnhance.vue";
|
||||||
|
import { UmByClassEnhance as UmTableClassEnhance } from "funjiaui";
|
||||||
|
// import UmDialog from "@/components/UmDialog/index.vue";
|
||||||
|
import Notice from "@/containers/viewModel/Notice";
|
||||||
|
import ImgPreview from "@/components/ImgPreview.vue";
|
||||||
|
import { ref, reactive, watch } from "vue";
|
||||||
|
import * as api from "@/common/api";
|
||||||
|
// import { fDT } from "marsLib/date";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const imgIndex = ref(0);
|
||||||
|
const ipcImgList = ref([]);
|
||||||
|
const imgPreviewInfo = reactive({
|
||||||
|
id: "",
|
||||||
|
imgUrl: "",
|
||||||
|
position: "",
|
||||||
|
time: "",
|
||||||
|
deviceName: ""
|
||||||
|
});
|
||||||
|
const currentDeviceId = ref(null);
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const traveInfomation = new Notice();
|
||||||
|
const formData = reactive<Notice>(traveInfomation)
|
||||||
|
// debugger;
|
||||||
|
Notice.userId = appStore.userInfo?.id;
|
||||||
|
|
||||||
|
watch(() => appStore.userInfo, (uI) => {
|
||||||
|
// Notice.userId
|
||||||
|
Notice.userId = uI?.id;
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ipc.singleListen = (rowData) => {
|
||||||
|
// initImgPreviewInfo(rowData);
|
||||||
|
// imgIndex.value = (ipcImgList.value || []).findIndex(item => rowData.id == item.id) || 0;
|
||||||
|
// visible.value = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const initImgPreviewInfo = (data) => {
|
||||||
|
imgPreviewInfo.id = data?.["id"];
|
||||||
|
imgPreviewInfo.imgUrl = data?.["imgUrl"];
|
||||||
|
imgPreviewInfo.position = data?.["position"];
|
||||||
|
imgPreviewInfo.time = data?.["time"];
|
||||||
|
imgPreviewInfo.deviceName = data?.["deviceName"];
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(imgIndex, (i) => {
|
||||||
|
initImgPreviewInfo(ipcImgList.value?.[i]);
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (!visible) {
|
||||||
|
imgIndex.value = 0;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const onDataChange = (data) => {
|
||||||
|
// ipcImgList.value = data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onImgIdxChange = (idx: TImgPreviewIdx) => {
|
||||||
|
let tempIdx = imgIndex.value;
|
||||||
|
tempIdx += idx;
|
||||||
|
|
||||||
|
if (tempIdx >= 0 && tempIdx < ipcImgList.value?.length) {
|
||||||
|
imgIndex.value = tempIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFire = async (key: string, value, data: any) => {
|
||||||
|
// imgIndex.value = 0;
|
||||||
|
// const resData = await api.getCaputreImgListByIpcId({ id: data })
|
||||||
|
// ipcImgList.value = resData.data?.objectList || [];
|
||||||
|
// initImgPreviewInfo(ipcImgList.value?.[0]);
|
||||||
|
currentDeviceId.value = value;
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.device-list) {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.img-preview-dialog) {
|
||||||
|
:local(.footer) {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['device-list']">
|
||||||
|
<h2>插件列表</h2>
|
||||||
|
<um-table-class-enhance class="role-right" :target="Plugin2" :data="[]"
|
||||||
|
:other-params="{ userId: appStore?.userInfo?.id }">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { UmByClassEnhance as UmTableClassEnhance } from "funjiaui";
|
||||||
|
import Plugin2 from "@/containers/viewModel/Plugin";
|
||||||
|
import { useAppStore } from "@/store/app";
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.device-list) {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.img-preview-dialog) {
|
||||||
|
:local(.footer) {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="$style['device-list']">
|
||||||
|
<h2>问答列表</h2>
|
||||||
|
<um-table-class-enhance class="role-right" :target="QA" :data="[]" @data-change="onDataChange" @fire="onFire">
|
||||||
|
</um-table-class-enhance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
// import UmTableClassEnhance from "@/components/UmTable/UmByClassEnhance.vue";
|
||||||
|
// import { UmByClassEnhance as UmTableClassEnhance } from "../../lib/funjiaui.es.js";
|
||||||
|
import { UmByClassEnhance as UmTableClassEnhance } from "funjiaui";
|
||||||
|
// import UmDialog from "@/components/UmDialog/index.vue";
|
||||||
|
// import QA from "@/containers/viewModel/QA";
|
||||||
|
import QA from "@/Magnet";
|
||||||
|
|
||||||
|
import { ref, reactive, watch } from "vue";
|
||||||
|
import * as api from "@/common/api";
|
||||||
|
// import { fDT } from "marsLib/date";
|
||||||
|
// import CaptureList from "@/containers/CaptureList.vue";
|
||||||
|
// import "funjiaui/style.css";
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const imgIndex = ref(0);
|
||||||
|
const ipcImgList = ref([]);
|
||||||
|
const imgPreviewInfo = reactive({
|
||||||
|
id: "",
|
||||||
|
imgUrl: "",
|
||||||
|
position: "",
|
||||||
|
time: "",
|
||||||
|
deviceName: ""
|
||||||
|
});
|
||||||
|
const currentDeviceId = ref(null);
|
||||||
|
|
||||||
|
// Ipc.singleListen = (rowData) => {
|
||||||
|
// initImgPreviewInfo(rowData);
|
||||||
|
// imgIndex.value = (ipcImgList.value || []).findIndex(item => rowData.id == item.id) || 0;
|
||||||
|
// visible.value = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const initImgPreviewInfo = (data) => {
|
||||||
|
imgPreviewInfo.id = data?.["id"];
|
||||||
|
imgPreviewInfo.imgUrl = data?.["imgUrl"];
|
||||||
|
imgPreviewInfo.position = data?.["position"];
|
||||||
|
imgPreviewInfo.time = data?.["time"];
|
||||||
|
imgPreviewInfo.deviceName = data?.["deviceName"];
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(imgIndex, (i) => {
|
||||||
|
initImgPreviewInfo(ipcImgList.value?.[i]);
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (!visible) {
|
||||||
|
imgIndex.value = 0;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const onDataChange = (data) => {
|
||||||
|
// ipcImgList.value = data || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const onImgIdxChange = (idx: TImgPreviewIdx) => {
|
||||||
|
let tempIdx = imgIndex.value;
|
||||||
|
tempIdx += idx;
|
||||||
|
|
||||||
|
if (tempIdx >= 0 && tempIdx < ipcImgList.value?.length) {
|
||||||
|
imgIndex.value = tempIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFire = async (key: string, value, data: any) => {
|
||||||
|
// imgIndex.value = 0;
|
||||||
|
// const resData = await api.getCaputreImgListByIpcId({ id: data })
|
||||||
|
// ipcImgList.value = resData.data?.objectList || [];
|
||||||
|
// initImgPreviewInfo(ipcImgList.value?.[0]);
|
||||||
|
currentDeviceId.value = value;
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style module lang="scss">
|
||||||
|
:global {
|
||||||
|
:local(.device-list) {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
:local(.img-preview-dialog) {
|
||||||
|
:local(.footer) {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"target": "esnext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"sourceMap": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"types": [
|
||||||
|
"element-plus/global"
|
||||||
|
],
|
||||||
|
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
|
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
"src/**/*.tsx",
|
||||||
|
"src/**/*.vue"
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"vite.config.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
|
import Components from 'unplugin-vue-components/vite'
|
||||||
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||||
|
import ElementPlus from 'unplugin-element-plus/vite'
|
||||||
|
import { resolve } from "path";
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue(),
|
||||||
|
AutoImport({
|
||||||
|
resolvers: [ElementPlusResolver()],
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
resolvers: [ElementPlusResolver()],
|
||||||
|
}),
|
||||||
|
ElementPlus({
|
||||||
|
// options
|
||||||
|
})
|
||||||
|
],
|
||||||
|
server: {
|
||||||
|
host: "0.0.0.0",
|
||||||
|
proxy: {
|
||||||
|
"^/api": {
|
||||||
|
target: "http://localhost:4873/",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
"^/static": {
|
||||||
|
target: "http://localhost:4873/resource/",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
"^/set/log/level": {
|
||||||
|
target: "http://192.168.1.89:4873/",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
"^/cache/image/": {
|
||||||
|
target: "http://192.168.1.102:1221/",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
"^/get/service/": {
|
||||||
|
target: "http://192.168.1.102:1221/",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": resolve(__dirname, "src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
cssCodeSplit: true, // 如果设置为false,整个项目中的所有 CSS 将被提取到一个 CSS 文件中
|
||||||
|
sourcemap: false, // 构建后是否生成 source map 文件。如果为 true,将会创建一个独立的 source map 文件
|
||||||
|
target: 'modules', // 设置最终构建的浏览器兼容目标。默认值是一个 Vite 特有的值——'modules' 还可设置为 'es2015' 'es2016'等
|
||||||
|
chunkSizeWarningLimit: 550, // 单位kb 打包后文件大小警告的限制 (文件大于此此值会出现警告)
|
||||||
|
assetsInlineLimit: 4096, // 单位字节(1024等于1kb) 小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0 可以完全禁用此项。
|
||||||
|
// minify: false,
|
||||||
|
minify:'terser', // 'terser', // 'terser' 相对较慢,但大多数情况下构建后的文件体积更小。'esbuild' 最小化混淆更快但构建后的文件相对更大。
|
||||||
|
lib: {
|
||||||
|
// 入口文件
|
||||||
|
entry: './src/Magnet.ts',
|
||||||
|
// 名称
|
||||||
|
name: 'Magnet',
|
||||||
|
// 格式,可选 'es', 'umd', 'iife'
|
||||||
|
formats: ['es','iife']
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: ['element-plus', 'vue', 'path', 'url', 'node','funjiaui','reflect-metadata','lodash-es','axois','funjia-axios'],
|
||||||
|
output: {
|
||||||
|
globals: {
|
||||||
|
"elementPlus": "element-plus",
|
||||||
|
"vue": "vue",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
terserOptions: {
|
||||||
|
compress: {
|
||||||
|
drop_console: true, // 生产环境去除console
|
||||||
|
drop_debugger: true // 生产环境去除debugger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user