Compare commits
259 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e510746da5 | ||
|
|
ad24b9e8d9 | ||
|
|
0daeb17792 | ||
|
|
409d625a95 | ||
|
|
1e42410b9e | ||
| c2898550f3 | |||
| 859407c81d | |||
| cf88c111a7 | |||
|
|
973b9e45bd | ||
| 54662297d4 | |||
| a329c96704 | |||
| 2f325c122c | |||
|
|
23b6d65f0c | ||
| 4556a93e8b | |||
| 6f7f7a1d09 | |||
|
|
8890df45b7 | ||
| 3eb9a9d9f1 | |||
| 880c4a0ba9 | |||
| c43e714c45 | |||
| e022b6861a | |||
| 079e6836e9 | |||
| 1e55a34574 | |||
| 8b7b700017 | |||
| a756eafd19 | |||
| 287a7a1f57 | |||
| 063a48e55b | |||
| 47277ee5eb | |||
| f256dd5d34 | |||
| 29990c0ba9 | |||
| 38189dfd11 | |||
| dc30a21d8f | |||
| 98632e6463 | |||
| 5b806fa489 | |||
| a3a75276ca | |||
|
|
1f386bf59c | ||
|
|
87afde90c4 | ||
| 20c663592d | |||
|
|
7dc6c42d7b | ||
| 64059e63ad | |||
| 43b84ff537 | |||
|
|
df9622c999 | ||
|
|
55f90ad01e | ||
|
|
a150feb640 | ||
| c09b7dc5f8 | |||
| e59cb9fa9e | |||
|
|
a91d2cda9c | ||
|
|
4309d54d09 | ||
|
|
62e7a425cc | ||
|
|
c728193842 | ||
|
|
1ba9ed33c5 | ||
| 66b9eabaec | |||
| 31a6f3bde2 | |||
| 459342d3e3 | |||
| 8d6f27e377 | |||
| 22a614959e | |||
| 8a8a61799f | |||
| 2ccf8d4aa0 | |||
| 4be4bf155f | |||
| 030a068b66 | |||
| d8197cfb4d | |||
| 18bf54c3e4 | |||
| 092ab763b8 | |||
|
|
b9707b3659 | ||
|
|
39011e6e9c | ||
| c979bbbe80 | |||
|
|
1bac48a717 | ||
| ce27de7ecc | |||
| be3703bd7a | |||
| b584460dd8 | |||
| a897319ef6 | |||
|
|
c0d121a7d7 | ||
| 98894a3582 | |||
| 8a337223f6 | |||
|
|
4dfd710acf | ||
| 94538e5e2f | |||
| e6c48e426a | |||
| 92b55c83dc | |||
|
|
36826154e0 | ||
| 15608dcc80 | |||
| 465671bf8c | |||
|
|
fac54b4f21 | ||
|
|
1b7d44ee19 | ||
|
|
357abc75cf | ||
|
|
5d09d6ebec | ||
| 35c8603002 | |||
| 574fb9bc6e | |||
| d2e810ad98 | |||
| 13d09216b1 | |||
| 5f0d568cb7 | |||
|
|
f699dc636f | ||
|
|
be6b362344 | ||
| 6f1770fd35 | |||
| c3b89a01ab | |||
|
|
26af0d1034 | ||
|
|
4577edc3c4 | ||
| dde16d4d02 | |||
| ddccaa4f32 | |||
|
|
fc03d50c07 | ||
| 182d43fd84 | |||
| 9e5365c96f | |||
| 3af945b0f3 | |||
| dbf6cfcd8b | |||
| 4d3c05c762 | |||
|
|
f0c3aaa59b | ||
|
|
919e073f78 | ||
| 1c5f3c8cdb | |||
| 06b5c8a595 | |||
| bdfe449803 | |||
| 04dd1d3f82 | |||
|
|
8ee0a90a5c | ||
|
|
ea9d79144a | ||
| 61e1af8c97 | |||
|
|
8d98e4c8c3 | ||
|
|
8bb03cbe3a | ||
| 8f50f9526b | |||
| 83ed53901d | |||
|
|
c983532bc7 | ||
| 846442e93a | |||
| e86dda5502 | |||
|
|
f3c715875d | ||
|
|
adc5df5bdb | ||
| c484ddb42f | |||
| fdacc38f17 | |||
|
|
dde3c944ed | ||
|
|
63a04f037c | ||
| 75b2b75065 | |||
| ccc7165298 | |||
|
|
fe03afe569 | ||
|
|
6ef8b88107 | ||
| 8a03e58f04 | |||
| 04c2ffe8de | |||
|
|
ccce5849f8 | ||
|
|
782a3b3088 | ||
| dfb3d478f0 | |||
| 53ed0eb7dd | |||
|
|
4bdd7e47f1 | ||
|
|
107446a3cb | ||
| 57e11ad63c | |||
| 47017d791d | |||
| b24b232493 | |||
|
|
918487e265 | ||
|
|
8a286cb65f | ||
|
|
67cd7c820f | ||
| 98be7d210f | |||
| f91ee04b65 | |||
| 310ec41122 | |||
|
|
0bb3ff32cb | ||
|
|
f8216befa3 | ||
|
|
18613f7243 | ||
| f6f4efa0c4 | |||
| b907c83aba | |||
| 9a5039e74e | |||
|
|
1e75be2bbe | ||
|
|
a873cebec1 | ||
| 2d2cbb28ba | |||
| 27302128eb | |||
|
|
35d00b9bfa | ||
|
|
39e982ce3a | ||
|
|
ef9d6c5e97 | ||
| 58b11a20eb | |||
| 06be7c0ff7 | |||
|
|
3af5775112 | ||
|
|
3e040b6cea | ||
| 62eaf32b75 | |||
|
|
1c2b751896 | ||
|
|
24328dbb51 | ||
| 2585c6bc76 | |||
|
|
f1e076de3f | ||
|
|
1d93015507 | ||
|
|
a510572631 | ||
| cd76e8cea9 | |||
|
|
282b173fad | ||
|
|
87d694ff0c | ||
| afe4e5f45d | |||
| c0e90c4510 | |||
|
|
bf493c49d0 | ||
|
|
cb6ff3c685 | ||
|
|
5cd1b0d887 | ||
|
|
c2bf4656eb | ||
|
|
27c704dd22 | ||
| 229198c53b | |||
| 817aceee78 | |||
| 0c77a93fb3 | |||
| b572c8aa56 | |||
|
|
d89ffada82 | ||
|
|
341555f68d | ||
|
|
6de3f69bb7 | ||
| b272e4c60f | |||
|
|
be1ebb4193 | ||
| afd7aa5f7c | |||
| 007ead7a1d | |||
| 1603aee96c | |||
|
|
3417b2fdbc | ||
| 72dcbd0ff6 | |||
| c87e0d428a | |||
| 5ffed3b4c7 | |||
|
|
797cdeaa75 | ||
| 8a13951dc8 | |||
| b203d9310b | |||
|
|
6605246539 | ||
| 2138f98df2 | |||
| 07ef4268eb | |||
|
|
d233336e63 | ||
|
|
1e1853149b | ||
|
|
d99aa6377d | ||
|
|
3e1168e794 | ||
| 43b068f3f6 | |||
| d15faa9698 | |||
| 19c336ab8f | |||
| 94b3568f19 | |||
|
|
1f5b5533d5 | ||
|
|
4f77b2c60e | ||
|
|
ff6f407079 | ||
|
|
cf8e5fbee4 | ||
|
|
decd86b217 | ||
| 56cb0013cf | |||
|
|
132b87b4c3 | ||
| 9d486af975 | |||
| 8f840f9c79 | |||
| 6d24175f93 | |||
| d16d7364bd | |||
|
|
1c7e2c2c3e | ||
| c65531f531 | |||
| 99fadc5563 | |||
|
|
ac61538b47 | ||
|
|
1e64b44b34 | ||
|
|
d215f469cc | ||
| 2a3c19900a | |||
| a5639b87ad | |||
| 2f56182ca9 | |||
| bf34cd1ed4 | |||
| dafc6ea37a | |||
|
|
7e876ce499 | ||
|
|
9244000fb0 | ||
| 2c4a3efba1 | |||
| 9859df5a4d | |||
| e61104d7c3 | |||
| f69122ff6d | |||
| c5a04e41fe | |||
|
|
5a3fb07f49 | ||
|
|
f2af236d56 | ||
| 361b573868 | |||
| 0ee42a673a | |||
| ef2856f0ff | |||
| 17bd08bea0 | |||
| 6a37d14707 | |||
|
|
02451a912f | ||
| ac9d30434b | |||
|
|
3ddb325953 | ||
| 680756464f | |||
|
|
6392c9b632 | ||
|
|
ddb6c4b83b | ||
|
|
b29b1a0dfa | ||
|
|
59a4df23ab | ||
|
|
1b6b501b9b | ||
|
|
34876246b1 | ||
|
|
8ac8eecb5c | ||
|
|
e1f3a39fe4 | ||
|
|
160a866130 |
@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 实验室管理系统
|
||||
VITE_APP_TITLE = 实验室信息管理系统
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 实验室管理系统
|
||||
VITE_APP_TITLE = 实验室信息管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'production'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = 实验室管理系统
|
||||
VITE_APP_TITLE = 实验室信息管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
||||
1
.gitignore
vendored
@ -21,3 +21,4 @@ selenium-debug.log
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
dist.zip
|
||||
|
||||
@ -2,29 +2,80 @@ import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import { defineConfig } from "eslint/config";
|
||||
|
||||
// 引入 TypeScript ESLint 插件和解析器
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
||||
|
||||
export default defineConfig([
|
||||
{ files: ["**/*.{js,mjs,cjs,vue}"], plugins: { js }, extends: ["js/recommended"] },
|
||||
{ files: ["**/*.{js,mjs,cjs,vue}"], languageOptions: { globals: globals.browser } },
|
||||
// 1. 基础 JS 规则(适用于 JS/Vue 文件)
|
||||
{
|
||||
files: ["**/*.{js,mjs,cjs,vue}"],
|
||||
plugins: { js },
|
||||
extends: ["js/recommended"]
|
||||
},
|
||||
// 2. 浏览器环境全局变量(适用于 JS/Vue/TS 文件)
|
||||
{
|
||||
files: ["**/*.{js,mjs,cjs,vue,ts,tsx}"],
|
||||
languageOptions: {
|
||||
globals: globals.browser
|
||||
}
|
||||
},
|
||||
// 3. Vue 基础规则
|
||||
pluginVue.configs["flat/essential"],
|
||||
// 4. Auto-import 插件配置(保持不变)
|
||||
{
|
||||
plugins: {
|
||||
'auto-import': {
|
||||
extensions: ['.js', '.mjs', '.jsx', '.vue'],
|
||||
extensions: ['.js', '.mjs', '.jsx', '.vue', '.ts', '.tsx'], // 增加 TS 扩展名
|
||||
},
|
||||
},
|
||||
},
|
||||
// 5. TypeScript 专属配置(核心)
|
||||
{
|
||||
// 仅对 TS/TSX 文件生效
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
// 指定 TS 解析器
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
// 解析器选项(需与 tsconfig.json 匹配)
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest", // 支持最新 ES 语法
|
||||
sourceType: "module", // 模块类型(ESM)
|
||||
project: "./tsconfig.json", // 指向项目的 tsconfig.json(启用类型检查)
|
||||
tsconfigRootDir: process.cwd(), // 确保找到 tsconfig.json 的根目录
|
||||
},
|
||||
},
|
||||
// 引入 TS 插件
|
||||
plugins: {
|
||||
"@typescript-eslint": tsPlugin,
|
||||
},
|
||||
// 继承 TS 推荐规则(可选,按需调整)
|
||||
extends: [
|
||||
"plugin:@typescript-eslint/recommended", // 基础推荐规则
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking" // 依赖类型检查的规则(需 project 配置)
|
||||
],
|
||||
// TS 专属规则(可自定义)
|
||||
rules: {
|
||||
// 示例:禁用某些严格规则(根据需求调整)
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "warn"
|
||||
}
|
||||
},
|
||||
// 6. 全局规则(覆盖所有文件)
|
||||
{
|
||||
rules: {
|
||||
'auto-import/export': 'error',
|
||||
// 可在此处添加适用于所有文件的规则
|
||||
// 例如关闭不必要的规则
|
||||
"no-undef": "off" // TS 已有类型检查,可关闭 JS 的 undef 检查
|
||||
},
|
||||
},
|
||||
// 7. Auto-import 配置(增加 TS 支持)
|
||||
{
|
||||
settings: {
|
||||
'auto-import': {
|
||||
// 自动导入的模块配置,与 unplugin-auto-import 配置一致
|
||||
imports: ['vue'],
|
||||
imports: ['vue', 'vue-router'], // 自动导入的模块
|
||||
// 增加 TS 扩展名
|
||||
extensions: ['.js', '.mjs', '.jsx', '.vue', '.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<title>实验室检验系统</title>
|
||||
<title>实验室信息管理系统</title>
|
||||
|
||||
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
|
||||
<style>
|
||||
|
||||
29
package.json
@ -1,24 +1,27 @@
|
||||
{
|
||||
"name": "czlis",
|
||||
"version": "8.0.0",
|
||||
"description": "实验室管理系统",
|
||||
"description": "实验室信息管理系统",
|
||||
"author": "工具",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"dev:prod": "vite",
|
||||
"build:prod": "vite build",
|
||||
"build:stage": "vite build --mode staging",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "2.3.1",
|
||||
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
||||
"@vueup/vue-quill": "1.2.0",
|
||||
"@vueuse/core": "10.6.1",
|
||||
"axios": "0.27.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"dayjs": "^1.11.18",
|
||||
"echarts": "5.4.3",
|
||||
"element-plus": "2.4.3",
|
||||
"element-plus": "^2.11.2",
|
||||
"file-saver": "2.0.5",
|
||||
"fuse.js": "6.6.2",
|
||||
"jquery": "^3.7.1",
|
||||
@ -26,30 +29,48 @@
|
||||
"js-cookie": "3.0.5",
|
||||
"jsbarcode": "^3.12.1",
|
||||
"jsencrypt": "3.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "2.1.7",
|
||||
"pinia-plugin-persistedstate": "^4.0.0",
|
||||
"pinyin-pro": "^3.26.0",
|
||||
"select2": "^4.1.0-rc.0",
|
||||
"vue": "3.4.0",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"sortablejs": "^1.14.0",
|
||||
"three": "^0.181.2",
|
||||
"vue": "3.5.23",
|
||||
"vue-cropper": "1.1.1",
|
||||
"vue-plugin-hiprint": "^0.0.60",
|
||||
"vue-router": "4.2.5",
|
||||
"vue3-print-nb": "^0.1.4",
|
||||
"vue3-seamless-scroll": "^3.0.2",
|
||||
"vue3-select2-component": "^0.1.7",
|
||||
"vuedraggable": "^4.1.0"
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vxe-pc-ui": "^4.3.2",
|
||||
"vxe-table": "^4.9.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.27.0",
|
||||
"@types/lodash": "^4.17.21",
|
||||
"@types/vue": "^2.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
||||
"@typescript-eslint/parser": "^8.46.2",
|
||||
"@vitejs/plugin-vue": "5.0.1",
|
||||
"@vue/compiler-sfc": "3.4.0",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-plugin-auto-import": "^0.1.1",
|
||||
"eslint-plugin-vue": "^10.1.0",
|
||||
"globals": "^16.1.0",
|
||||
"rollup-plugin-visualizer": "^6.0.5",
|
||||
"sass": "1.69.5",
|
||||
"terser": "^5.46.0",
|
||||
"typescript": "^5.9.3",
|
||||
"unplugin-auto-import": "0.17.1",
|
||||
"unplugin-vue-setup-extend-plus": "1.0.0",
|
||||
"vite": "5.0.4",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-plugin-svg-icons": "2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
4498
pnpm-lock.yaml
generated
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 134 KiB |
16
src/App.vue
@ -5,6 +5,18 @@
|
||||
<script setup>
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import { handleThemeStyle } from '@/utils/theme'
|
||||
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
|
||||
import { useFingerprint } from '@/utils/useFingerprint';
|
||||
import { useCommonStore } from '@/store/modules/commonStore'
|
||||
const mbStore = useCommonStore();
|
||||
// 使用自定义hook获取指纹信息
|
||||
const { fingerprint, getFingerprint } = useFingerprint();
|
||||
|
||||
if (!mbStore.fingerprint) {
|
||||
// 重新获取指纹
|
||||
getFingerprint();
|
||||
mbStore.setFingerprint(fingerprint)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
@ -12,4 +24,8 @@ onMounted(() => {
|
||||
handleThemeStyle(useSettingsStore().theme)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
34
src/api/backApply/index.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 查询数据列表
|
||||
export function applyQueryList(query?: Object) {
|
||||
return request({
|
||||
url: '/cancelCheck/queryList',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 获取明细数据
|
||||
export function queryXmDetail(query?: Object) {
|
||||
return request({
|
||||
url: '/cancelCheck/queryDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 退检
|
||||
export function confirmRefund(query?: Object) {
|
||||
return request({
|
||||
url: '/cancelCheck/confirm',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 拒绝退费
|
||||
export function refuseRefund(query?: Object) {
|
||||
return request({
|
||||
url: '/cancelCheck/refuse',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
51
src/api/batch/index.ts
Normal file
@ -0,0 +1,51 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取模版数据
|
||||
export function getInputMdl(query?: Object) {
|
||||
return request({
|
||||
url: '/batchIn/getInputMdl',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 获取模版明细数据
|
||||
export function getInputMdlDetail(query?: Object) {
|
||||
return request({
|
||||
url: '/batchIn/getInputMdlDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 确认模版数据
|
||||
export function confirmInputMdl(query?: Object) {
|
||||
return request({
|
||||
url: '/batchIn/confirmInputMdl',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 调整数据
|
||||
export function adjustData(query?: Object) {
|
||||
return request({
|
||||
url: '/batchCheck/adjustData',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 读取数据
|
||||
export function readData(query?: Object) {
|
||||
return request({
|
||||
url: '/batchCheck/readData',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 保存数据
|
||||
export function saveData(query?: Object) {
|
||||
return request({
|
||||
url: '/batchCheck/saveData',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
140
src/api/checkCode/index.ts
Normal file
@ -0,0 +1,140 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 生成条码
|
||||
export function addObj(query?: Object) {
|
||||
return request({
|
||||
url: 'zyreq/add',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 查询申请单列表
|
||||
export function fetchCodeList(query?: Object) {
|
||||
return request({
|
||||
url: '/zyreq/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询项目
|
||||
export function fetchCodeDetail(query?: Object) {
|
||||
return request({
|
||||
url: 'zyreq/detail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 执行条码
|
||||
export function fetchCodeExec(query?: Object) {
|
||||
return request({
|
||||
url: '/zyreq/exec',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 执行条码
|
||||
export function printSendSample(query?: Object) {
|
||||
return request({
|
||||
url: '/zyreq/printSendSample',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 获取申请单主表信息
|
||||
export function fetchCodeReqmain(query?: Object) {
|
||||
return request({
|
||||
url: 'zyreq/reqmain',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询报告单列表
|
||||
export function reportList(query?: Object) {
|
||||
return request({
|
||||
url: '/report/ReportList',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询报告Pdf预览
|
||||
export function reportViewPdf(query?: Object) {
|
||||
return request({
|
||||
url: '/report/pdf',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询报告Pdf打印
|
||||
export function reportPrintPdf(query?: Object) {
|
||||
return request({
|
||||
url: '/report/print',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 查询项目报告
|
||||
export function reportResult(query?: Object) {
|
||||
return request({
|
||||
url: '/report/result',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 查询微生物报告
|
||||
export function reportMedList(query?: Object) {
|
||||
return request({
|
||||
url: '/report/MedList',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 查询微生物报告
|
||||
export function reportFsresult(query?: Object) {
|
||||
return request({
|
||||
url: '/report/fsresult',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 打印机插件检查
|
||||
export function printcheck(query?: Object) {
|
||||
return request({
|
||||
url: '/zyreq/printcheck',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 打印机插件设置
|
||||
export function printsetup(query?: Object) {
|
||||
return request({
|
||||
url: '/zyreq/printsetup',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 取消采样
|
||||
export function cancelExecSQD(query?: Object) {
|
||||
return request({
|
||||
url: '/zyreq/cancelExecSQD',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
export function getSQDDetailList(query?: Object) {
|
||||
return request({
|
||||
url: '/report/getSQDDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
export function getCdssUrl(query?: Object) {
|
||||
return request({
|
||||
url: '/report/InterfaceData',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
30
src/api/liswork/advancedReview/index.ts
Normal file
@ -0,0 +1,30 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
|
||||
//获取报告列表
|
||||
export function queryList(query?: Object) {
|
||||
return request({
|
||||
url: '/labCheckrules/queryList',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
//保存报告列表
|
||||
export function updateRules(data: Object) {
|
||||
return request({
|
||||
url: '/labCheckrules/update',
|
||||
method: 'post',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
//删除报告列表
|
||||
export function deleteRules(data: Object) {
|
||||
return request({
|
||||
url: '/labCheckrules/delete',
|
||||
method: 'get',
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
56
src/api/liswork/batch/index.ts
Normal file
@ -0,0 +1,56 @@
|
||||
// @ts-ignore
|
||||
import request from "@/utils/request";
|
||||
|
||||
//获取批量审核列表数据
|
||||
export function queryBatchCheckListService(query: any) {
|
||||
return request({
|
||||
url: "/batchCheck/query",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
//批量审核
|
||||
export function batchCheckService(data: any) {
|
||||
return request({
|
||||
url: "/batchCheck/checkData",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
//取消批量审核
|
||||
export function cancelBatchCheckService(data: any) {
|
||||
return request({
|
||||
url: "/batchCheck/unCheckData",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
//获取检验结果明细数据
|
||||
export function queryBatchCheckDetailService(query: any) {
|
||||
return request({
|
||||
url: "/batchCheck/queryDetailResult",
|
||||
method: "get",
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 批量打印查询
|
||||
export function queryBatchPrintService(query: any) {
|
||||
return request({
|
||||
url: "/batchPrint/queryList",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 批量打印数据
|
||||
export function batchPrintAll(query: any) {
|
||||
return request({
|
||||
url: "/batchPrint/printAll",
|
||||
method: "post",
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典数据列表
|
||||
export function queryComDictListService(query) {
|
||||
return request({
|
||||
url: '/comdict/query',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//增加字典数据
|
||||
export function addComDictService(data) {
|
||||
return request({
|
||||
url: '/comdict/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//修改字典数据
|
||||
export function updateComDictService(data) {
|
||||
return request({
|
||||
url: '/comdict/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 根据字典类型查询字典数据信息
|
||||
export function getComDicts(zdlb) {
|
||||
return request({
|
||||
url: '/comdict/getComDicts',
|
||||
method: 'get',
|
||||
params: zdlb
|
||||
})
|
||||
}
|
||||
|
||||
47
src/api/liswork/dict/ComDict.ts
Normal file
@ -0,0 +1,47 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典数据列表
|
||||
export function queryComDictListService(query?: Object) {
|
||||
return request({
|
||||
url: '/comdict/query',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//增加字典数据
|
||||
export function addComDictService(data?: Object) {
|
||||
return request({
|
||||
url: '/comdict/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//修改字典数据
|
||||
export function updateComDictService(data?: Object) {
|
||||
return request({
|
||||
url: '/comdict/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
|
||||
}
|
||||
//删除字典数据
|
||||
export function delComDictService(data?: Object) {
|
||||
return request({
|
||||
url: '/comdict/del',
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 根据字典类型查询字典数据信息
|
||||
export function getComDicts(zdlb?: Object) {
|
||||
return request({
|
||||
url: '/comdict/getComDicts',
|
||||
method: 'get',
|
||||
params: zdlb
|
||||
})
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典数据列表
|
||||
export function querylabInstrList(query) {
|
||||
return request({
|
||||
url: '/instr/query',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询字典数据列表
|
||||
export function querylabInstrListByLisgroup(query) {
|
||||
return request({
|
||||
url: '/instr/querybylisgroup',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
19
src/api/liswork/dict/LabInstr.ts
Normal file
@ -0,0 +1,19 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典数据列表
|
||||
export function querylabInstrList(query?: Object) {
|
||||
return request({
|
||||
url: '/instr/query',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询字典数据列表
|
||||
export function querylabInstrListByLisgroup(query?: Object) {
|
||||
return request({
|
||||
url: '/instr/querybylisgroup',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
30
src/api/liswork/germ/med.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// 抗菌药物字典 xm_med
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询药物列表(后端全量返回,不分页)
|
||||
export function listMed(params) {
|
||||
return request({
|
||||
url: '/xmMed/query',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 新增/修改药物(后端按 ywdh 存在即更新),入参为数组
|
||||
export function addMed(data) {
|
||||
return request({
|
||||
url: '/xmMed/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除药物
|
||||
export function delMed(ywdh) {
|
||||
return request({
|
||||
url: '/xmMed/del',
|
||||
method: 'get',
|
||||
params: { ywdh }
|
||||
})
|
||||
}
|
||||
39
src/api/liswork/germ/medgroup.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// 常用抗生素组 xm_medgroup
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询(不传条件返回全部明细,前端去重得到组名)
|
||||
export function listMedgroup(params) {
|
||||
return request({
|
||||
url: '/xmMedgroup/query',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 新增明细(无 @RequestBody,参数走 query)
|
||||
export function addMedgroup(params) {
|
||||
return request({
|
||||
url: '/xmMedgroup/add',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改明细(无 @RequestBody,参数走 query)
|
||||
export function updateMedgroup(params) {
|
||||
return request({
|
||||
url: '/xmMedgroup/update',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除明细
|
||||
export function delMedgroup(params) {
|
||||
return request({
|
||||
url: '/xmMedgroup/del',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
39
src/api/liswork/germ/medinter.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// 抗生素通道号 xm_medinter
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询某仪器的通道号列表
|
||||
export function listMedinter(params) {
|
||||
return request({
|
||||
url: '/xmMedinter/query',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 新增通道号
|
||||
export function addMedinter(data) {
|
||||
return request({
|
||||
url: '/xmMedinter/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改通道号(只改药物)
|
||||
export function updateMedinter(data) {
|
||||
return request({
|
||||
url: '/xmMedinter/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除通道号
|
||||
export function delMedinter(params) {
|
||||
return request({
|
||||
url: '/xmMedinter/del',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
148
src/api/liswork/labItem/LabItemApi.ts
Normal file
@ -0,0 +1,148 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
//检验项目界面
|
||||
|
||||
|
||||
//获取列表数据
|
||||
export function queryXmInfoNewService(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/query',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//获取明细数据
|
||||
export function queryXmInfoNewDetailService(xmid: any, yq: any, xmdh: any) {
|
||||
return request({
|
||||
url: '/xminfo/queryDetail',
|
||||
method: 'get',
|
||||
params: {
|
||||
xmid,
|
||||
yq,
|
||||
xmdh
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//获取项目基本信息
|
||||
export function queryXmInfoNew(xmgl: any) {
|
||||
return request({
|
||||
url: '/xminfo/queryXmInfoNew',
|
||||
method: 'get',
|
||||
params: {
|
||||
xmgl
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//获取危急值特定判断条件数据
|
||||
export function queryXmAlarmdetailNew(xmid: number) {
|
||||
return request({
|
||||
url: '/xminfo/queryXmAlarmdetailNew',
|
||||
method: 'get',
|
||||
params: { xmid }
|
||||
})
|
||||
}
|
||||
|
||||
//新增危急值特定判断条件数据
|
||||
export function addXmAlarmdetailNew(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/addXmAlarmdetailNew',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
|
||||
//新增危急值特定判断条件数据
|
||||
export function delXmAlarmdetailNew(xmid: number, seq: number) {
|
||||
return request({
|
||||
url: '/xminfo/delXmAlarmdetailNew',
|
||||
method: 'get',
|
||||
params: {
|
||||
xmid,
|
||||
seq
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//保存数据
|
||||
export function saveDataService(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/update',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
|
||||
//删除常用取值
|
||||
export function delXmValNewService(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/delXmValNew',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//删除常见描述
|
||||
export function delXmTextresultNew(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/delXmTextresultNew',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//删除仪器对照
|
||||
export function deleteXmInfoVs(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/delvs',
|
||||
method: 'delete',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
//删除检验项目
|
||||
export function deleteXmInfoService(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/del',
|
||||
method: 'delete',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//删除参考值明细
|
||||
export function delXmRefNew(query: any) {
|
||||
return request({
|
||||
url: '/xminfo/delXmRefNew',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//查询批量数据
|
||||
export function queryBatchList(query?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/queryBatch',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//批量新增数据
|
||||
export function addBatch(query?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/addBatch',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//批量删除数据
|
||||
export function delBatch(query?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/delBatch',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
206
src/api/liswork/micro/index.ts
Normal file
@ -0,0 +1,206 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
|
||||
// 查询微生物数据列表
|
||||
export function wswsampleList(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/wswsamplelist',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询微生物数据列表 分页
|
||||
export function wswsamplelistpage(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/wswsamplelistpage',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取微生物样本信息
|
||||
export function wswsampleinfo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/germsampleinfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取微生物结果信息
|
||||
export function sampleMedInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getresultlist',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取药敏数据
|
||||
export function getresultmedList(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getresultmedlist',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取专家评语字典
|
||||
export function getgermtextdict(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getgermtextdict',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 写入专家评语
|
||||
export function savetestResult(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/savetestresult',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 获取操作记录
|
||||
export function getComLog(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getcomlog',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//新增结果明细
|
||||
export function newresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/newresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//修改结果明细
|
||||
export function changeresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/changeresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//修改结果明细
|
||||
export function saveresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/saveresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//获取药敏字典
|
||||
export function getmeddictList(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getmeddict',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//获取药敏模板
|
||||
export function getmedgroupList(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getmedgrouplist',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//获取药敏模板明细
|
||||
export function getmedgroupMbList(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getmedgroup',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//保存药敏结果
|
||||
export function savemedresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/savemedresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//保存所有药敏结果
|
||||
export function savemedresultall(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/savemedresultall',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//删除药敏结果
|
||||
export function deletemedresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/deletemedresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//获取培养基记录
|
||||
export function getmediumList(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getmedium',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//获取培养基字典
|
||||
export function getbactmediumList(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/getbactmedium',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//新增培养基
|
||||
export function insertmedium(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/insertmedium',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//修改培养基
|
||||
export function updatemedium(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/updatemedium',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//删除培养基
|
||||
export function deletemedium(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/deletemedium',
|
||||
method: 'delete',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//删除培养基 Array
|
||||
export function deletemediums(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/deletemedium',
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
}
|
||||
//微生物报告审核
|
||||
export function cbebCheck(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/check',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//修改样本检验日期
|
||||
export function changepatjyrq(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkgerm/changepatjyrq',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
70
src/api/liswork/order/index.ts
Normal file
@ -0,0 +1,70 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
|
||||
//获取项目信息
|
||||
export function queryXmInfoList(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/queryXmInfoList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//保存病人信息
|
||||
export function saveReqInfo(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/saveReqInfo',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//保存病人信息
|
||||
export function queryPatList(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/queryPatList',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//查询病人信息
|
||||
export function queryPatInfo(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/queryPatInfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//不可开单项目列表
|
||||
export function queryCreateReqList(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/queryCreateReqList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
//可开单项目列表
|
||||
export function queryCanCreateReqList(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/queryCanCreateReqList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//保存可开单项目
|
||||
export function saveCanCreaeReqList(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/saveCanCreaeReqList',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
//获取病人明细信息
|
||||
export function queryPatDetail(query: any) {
|
||||
return request({
|
||||
url: '/reqInput/queryPatDetail',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
245
src/api/liswork/qualityControl/index.ts
Normal file
@ -0,0 +1,245 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 保存数据
|
||||
export function saveOpt(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/saveOpt',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 查询项目的质控规则
|
||||
export function queryRules(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/queryRules',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 保存质控项目数据
|
||||
export function saveQCItem(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/saveQCItem',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 普通标本和质控标本对应关系
|
||||
export function queryDataFromSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/queryDataFromSample',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 查询质控品数据
|
||||
export function queryQcSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/queryQcSample',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询质控品数据
|
||||
export function saveQcSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/saveQcFromSample',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// -删除普通标本和质控标本对应关系
|
||||
export function deleteQcSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/deleteQcFromSample',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 查询质控批号
|
||||
export function queryBatch(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/query',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 新增质控批号
|
||||
export function addBatchno(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/addBatchno',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 修改质控批号
|
||||
export function updateBatchno(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/updateBatchno',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 删除质控批号
|
||||
export function delBatchno(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/delBatchno',
|
||||
method: 'delete',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 查询质控批号 获取项目列表
|
||||
export function queryBatchXm(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/queryVal',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取项目列表
|
||||
export function queryValXmdh(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/queryValXmdh',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 保存质控品参数
|
||||
export function saveBtQcSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/saveQcSample',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 查询质控品录入
|
||||
export function getqcval(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/getqcvalitem',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 保存质控数据(当天所有项目)
|
||||
export function saveqcvalItem(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/saveqcvalitem',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 获取质控项目
|
||||
export function queryXmItem(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/queryitem',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
// 查询质控数据(单项目一个月)
|
||||
export function getqcvalmonth(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/getqcvalmonth',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//保存质控数据(单项目一个月)
|
||||
export function saveQcvalMonth(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/saveqcvalmonth',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//复制靶值
|
||||
export function copyQcSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/copyQcSample',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//删除靶值
|
||||
export function delQcSample(data?: Object) {
|
||||
return request({
|
||||
url: '/qc/delQcSample',
|
||||
method: 'delete',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//查询质控室内数据(月统计)
|
||||
export function getmonthst(data?: Object) {
|
||||
return request({
|
||||
url: '/qcstat/getmonthst',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//查询月室内质控小结
|
||||
export function getmonthpj(data?: Object) {
|
||||
return request({
|
||||
url: '/qcstat/getmonthpj',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//保存月室内质控小结
|
||||
export function savemonthpj(data?: Object) {
|
||||
return request({
|
||||
url: '/qcstat/savemonthpj',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//查询月失控情况总结
|
||||
export function getmonthskzj(data?: Object) {
|
||||
return request({
|
||||
url: '/qcstat/getmonthskzj',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//保存月失控情况总结
|
||||
export function savemonthskzj(data?: Object) {
|
||||
return request({
|
||||
url: '/qcstat/savemonthskzj',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//查询质控数据
|
||||
export function qcgraphList(data?: Object) {
|
||||
return request({
|
||||
url: '/qcgraph/query',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//查询质控参数列表
|
||||
export function querySample(data?: Object) {
|
||||
return request({
|
||||
url: '/qcgraph/querysample',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//计算靶值
|
||||
export function qcCalc(data?: Object) {
|
||||
return request({
|
||||
url: '/qcgraph/calc',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
//质量汇总查询
|
||||
export function ncisQuery(data?: Object) {
|
||||
return request({
|
||||
url: '/ncis/query',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询数据列表
|
||||
export function queryLabPatList(query) {
|
||||
return request({
|
||||
url: '/liswork/samplelist',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询数据
|
||||
export function queryLabPat(query) {
|
||||
return request({
|
||||
url: '/liswork/sampleinfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询服务器时间
|
||||
export function getDate() {
|
||||
return request({
|
||||
url: '/liswork/getdate',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
//增加字典数据
|
||||
export function addLabPatService(data) {
|
||||
return request({
|
||||
url: '/liswork/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//修改字典数据
|
||||
export function updateLabPatService(data) {
|
||||
return request({
|
||||
url: '/liswork/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 查询数据列表
|
||||
export function queryLabResults(query) {
|
||||
return request({
|
||||
url: '/liswork/resultinfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 批量删除结果
|
||||
export function deleteresult(data) {
|
||||
return request({
|
||||
url: '/liswork/deleteresult',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
491
src/api/liswork/work/LisWork.ts
Normal file
@ -0,0 +1,491 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
import { ElLoading, ElMessage } from 'element-plus'
|
||||
|
||||
// 查询数据列表
|
||||
export function queryLabPatList(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/samplelist',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询数据
|
||||
export function queryLabPat(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/sampleinfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询服务器时间
|
||||
export function getDate() {
|
||||
return request({
|
||||
url: '/liswork/getdate',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
//新增结果明细
|
||||
export function newresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/newresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
//修改结果明细
|
||||
export function changeresult(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/changeresult',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
//新建样本病人信息
|
||||
export function updateLabPat(data?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/changepat',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 修改病人信息
|
||||
export function changepatcolumn(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/changepatcolumn',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询结果数据列表
|
||||
export function queryLabResults(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/resultinfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询检验项目
|
||||
export function queryXmInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/queryxminfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询常用取值
|
||||
export function queryXmVal(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/queryxmval',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 批量删除结果
|
||||
export function deleteresult(data?: Object) {
|
||||
return request({
|
||||
url: '/liswork/deleteresult',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
|
||||
}
|
||||
//审核
|
||||
export function check2(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/check2',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
|
||||
}
|
||||
//取消审核
|
||||
export function uncheck2(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/uncheck2',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//取消审核原因
|
||||
export function unconfirmlog(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/unconfirmlog',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
//取消审核原因
|
||||
export function check1(query?: Object) {
|
||||
return request({
|
||||
url: 'lisworkoper/check1',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 获取操作userId
|
||||
export function checkuser(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/checkuserid',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
export function reglimit(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/reglimit',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function printsample(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/printsample',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 打印报告单
|
||||
export function printListwork(query?: Object) {
|
||||
// 1. 开启 loading 效果
|
||||
const loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
text: '数据加载中...',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
// 2. 发起请求并处理 loading 关闭
|
||||
return request({
|
||||
url: '/liswork/print',
|
||||
method: 'get',
|
||||
params: query
|
||||
}).finally(() => {
|
||||
loadingInstance.close()
|
||||
}).catch((error: any) => {
|
||||
ElMessage.error('数据加载失败,请稍后重试')
|
||||
throw error
|
||||
})
|
||||
}
|
||||
// 查询默认值
|
||||
export function loadDefault(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/loaddefault',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 历史对照
|
||||
export function historyInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/history',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 其他结果
|
||||
export function otherinstr(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/otherinstr',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 其他结果明细
|
||||
export function otherInstrDetail(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/otherinstrdetail',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 收费信息
|
||||
export function reqdetail(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/reqdetail',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取收费信息报告明细
|
||||
export function reqdetailmx(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/reqdetailmx',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 左边form参数
|
||||
export function instrdconfig(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/instrdconfig',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 医生校验
|
||||
export function checkYsUser(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/checkuserid',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 删除样本
|
||||
export function delSample(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/delsample',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取标本流转信息
|
||||
export function reqinfo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/reqinfo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取检验结果图片信息
|
||||
export function resultgraph(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/resultgraph',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取组合项目模板
|
||||
export function inputmdl(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/inputmdl',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 项目模板输入结果
|
||||
export function setinputmdl(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/setinputmdl',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 保存病人结果
|
||||
export function saveResult(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/saveresult',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 获取复查结果
|
||||
export function redoResult(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/redo',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 保存复查结果
|
||||
export function saveRedo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/saveredo',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 交换复查结果
|
||||
export function swapRedo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/swapredo',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 删除复查结果
|
||||
export function delRedo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/deleteRedo',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 仪器组可操作仪器查询
|
||||
export function getGroupInstrdList(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/getGroupInstrdList',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 结果修改记录
|
||||
export function getresultchangelog(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/getresultchangelog',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取临床意义
|
||||
export function clinicInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkpageinfo/clinicref',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 指定为某样本复查结果
|
||||
export function setredoSample(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/setredosample',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 锁定报告
|
||||
export function lockSample(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/locksample',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 解锁报告
|
||||
export function unLockSample(query?: Object) {
|
||||
return request({
|
||||
url: '/lisworkoper/unlocksample',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查看电子病历
|
||||
export function emrquery(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/emrquery',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查看患者360视图
|
||||
export function allPatquery(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/allpatquery',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 双工流水线
|
||||
export function datalink(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/datalink',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 批量更改流水线状态
|
||||
export function changeLinkList(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/changelinklist',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 清除所有未做项目
|
||||
export function clearnotComplete(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/clearnotcomplete',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查看备份数据
|
||||
export function viewBackup(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/viewbackup',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 未建项目结果
|
||||
export function noiteMresult(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/noitemresult',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 项目与通道号对照
|
||||
export function setitemInter(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/setiteminter',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 清除打印标志
|
||||
export function clearPrintflag(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/clearprintflag',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 自动签收条码
|
||||
export function autosavebarcode(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/autosavebarcode',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 条码签收
|
||||
export function querybarcode(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/querybarcode',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 手动保存签收条码
|
||||
export function saveBarcode(query?: Object) {
|
||||
return request({
|
||||
url: '/liswork/savebarcode',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 拒收条码
|
||||
export function refusedbarcode(query?: Object) {
|
||||
return request({
|
||||
url: '/refused/getData',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 保存拒收条码
|
||||
export function refusedSaveData(query?: Object) {
|
||||
return request({
|
||||
url: '/refused/saveData',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 查询申请单全程信息
|
||||
export function wholeprocessList(query?: Object) {
|
||||
return request({
|
||||
url: '/wholeprocess/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
41
src/api/liswork/xmKnowledge/xmKnowledgeApi.ts
Normal file
@ -0,0 +1,41 @@
|
||||
//知识库
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
//查询数据
|
||||
export function queryService(params:any){
|
||||
return request({
|
||||
url: '/xmKnowledge/query',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//查询明细数据
|
||||
export function queryDetailService(xmdh: string){
|
||||
return request({
|
||||
url: '/xmKnowledge/detail',
|
||||
method: 'get',
|
||||
params: {
|
||||
xmdh
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//新增数据
|
||||
export function addService(params:any){
|
||||
return request({
|
||||
url: '/xmKnowledge/add',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//删除数据
|
||||
export function delService(params:any){
|
||||
return request({
|
||||
url: '/xmKnowledge/del',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
150
src/api/liswork/xmmb/index.ts
Normal file
@ -0,0 +1,150 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
|
||||
// 查询模板列表
|
||||
export function queryMbList(query?: Object) {
|
||||
return request({
|
||||
url: '/labInputmdl/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询明细数据
|
||||
export function queryDetail(query?: Object) {
|
||||
return request({
|
||||
url: '/labInputmdl/queryDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 新增模板
|
||||
export function addXmInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/labInputmdl/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 修改模板
|
||||
export function updateXmInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/labInputmdl/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 删除模板
|
||||
export function deleteXmInfo(query?: Object) {
|
||||
return request({
|
||||
url: '/labInputmdl/delete',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 删除明细数据
|
||||
export function deleteDetail(query?: Object) {
|
||||
return request({
|
||||
url: '/labInputmdl/deleteDetail',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 查询项目组合
|
||||
export function xmCompQuery(query?: Object) {
|
||||
return request({
|
||||
url: '/xmComp/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 增加项目组合
|
||||
export function addxmComp(query?: Object) {
|
||||
return request({
|
||||
url: '/xmComp/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 修改项目组合
|
||||
export function editxmComp(query?: Object) {
|
||||
return request({
|
||||
url: '/xmComp/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 删除项目组合
|
||||
export function delxmComp(query?: Object) {
|
||||
return request({
|
||||
url: '/xmComp/del',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询明细数据
|
||||
export function queryDetailComp(query?: Object) {
|
||||
return request({
|
||||
url: '/xmComp/queryDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 删除明细数据
|
||||
export function deleteDetailComp(query?: Object) {
|
||||
return request({
|
||||
url: '/xmComp/deleteDetail',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 查询仪器组合列表
|
||||
export function queryInstrgroupList(query?: Object) {
|
||||
return request({
|
||||
url: '/instrgroup/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 新增仪器组合
|
||||
export function addInstrgroup(query?: Object) {
|
||||
return request({
|
||||
url: '/instrgroup/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 修改仪器组合
|
||||
export function updateInstrgroup(query?: Object) {
|
||||
return request({
|
||||
url: '/instrgroup/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 删除仪器组合
|
||||
export function deleteInstrgroup(query?: Object) {
|
||||
return request({
|
||||
url: '/instrgroup/delete',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询明细数据
|
||||
export function queryDetailInstrgroup(query?: Object) {
|
||||
return request({
|
||||
url: '/instrgroup/queryDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 删除明细数据
|
||||
export function delDetailInstrgroup(query?: Object) {
|
||||
return request({
|
||||
url: '/instrgroup/deleteDetail',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
|
||||
55
src/api/liswork/xtwh/AntibioticBreakpointApi.ts
Normal file
@ -0,0 +1,55 @@
|
||||
// 抗生素折点范围字典 API
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取菌属列表(从 xm_meddetail 表)
|
||||
export function getGermClassList(params?: any) {
|
||||
return request({
|
||||
url: '/xm/meddetail/germclass/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取抗生素字典列表(从 xm_med 表)
|
||||
export function getAntibioticList(params?: any) {
|
||||
return request({
|
||||
url: '/xm/med/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取折点范围数据
|
||||
export function getBreakpointList(params: any) {
|
||||
return request({
|
||||
url: '/xm/breakpoint/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 保存折点范围
|
||||
export function saveBreakpoint(data: any) {
|
||||
return request({
|
||||
url: '/xm/breakpoint',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 批量保存折点范围
|
||||
export function batchSaveBreakpoint(data: any[]) {
|
||||
return request({
|
||||
url: '/xm/breakpoint/batch',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除折点范围
|
||||
export function deleteBreakpoint(id: number) {
|
||||
return request({
|
||||
url: `/xm/breakpoint/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
197
src/api/liswork/xtwh/ComOpt.ts
Normal file
@ -0,0 +1,197 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
|
||||
// 查询参数列表
|
||||
export function paramList(query?: Object) {
|
||||
return request({
|
||||
url: '/param/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 获取默认值
|
||||
export function getdef(query?: Object) {
|
||||
return request({
|
||||
url: '/param/getdef',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询某个参数的值
|
||||
export function queryValue(query?: Object) {
|
||||
return request({
|
||||
url: '/param/queryValue',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 修改参数列表
|
||||
export function updateParam(query?: Object) {
|
||||
return request({
|
||||
url: '/param/update',
|
||||
method: 'put',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 删除参数列表
|
||||
export function delParam(query?: Object) {
|
||||
return request({
|
||||
url: '/param/del',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询参数列表树状结构
|
||||
export function paramTree(query?: Object) {
|
||||
return request({
|
||||
url: '/param/queryTree',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询某个参数
|
||||
export function queryOneService(yq: string, xxdh: string) {
|
||||
return request({
|
||||
url: '/param/queryOne',
|
||||
method: 'get',
|
||||
params: { yq, xxdh }
|
||||
});
|
||||
}
|
||||
// 查询滤光片波长对照表
|
||||
export function queryFilter(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/queryFilter',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 新增滤光片波长对照表
|
||||
export function addXmFilter(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/addXmFilter',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 删除滤光片波长对照表
|
||||
export function delXmFilter(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/delXmFilter',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 获取试剂维护数据
|
||||
export function queryXmLot(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/queryXmLot',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 新增试剂维护数据
|
||||
export function addXmLot(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/addXmLot',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 删除试剂维护数据
|
||||
export function delXmLot(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/delXmLot',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 获取试剂厂家
|
||||
export function querySjcs(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/querySjcs',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 查询检验项目排序
|
||||
export function getitemsort(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/getitemsort',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 保存检验项目排序
|
||||
export function saveitemsort(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/saveitemsort',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 查询检验项目通道号
|
||||
export function getitemtdh(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/getitemtdh',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 保存检验项目通道号
|
||||
export function saveitemtdh(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/saveitemtdh',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 删除检验项目通道号
|
||||
export function delitemtdh(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/delitemtdh',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 获取仪器参数
|
||||
export function querydouble(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/querydouble',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 保存仪器参数
|
||||
export function savedouble(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/savedouble',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 获取参数默认模板
|
||||
export function querymbmc(data?: Object) {
|
||||
return request({
|
||||
url: '/xminfo/querymbmc',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 查询调整列表
|
||||
export function queryInputcol(data?: Object) {
|
||||
return request({
|
||||
url: '/inputcol/query',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 整体调整列表
|
||||
export function saveInputcol(data?: Object) {
|
||||
return request({
|
||||
url: '/inputcol/save',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
39
src/api/liswork/xtwh/ReportSettingApi.ts
Normal file
@ -0,0 +1,39 @@
|
||||
//报告单设置界面
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
//新增数据
|
||||
export function addReportService(LabReportInstr: Object){
|
||||
return request({
|
||||
url: '/labReportinstr/add',
|
||||
method: 'post',
|
||||
data: LabReportInstr
|
||||
})
|
||||
}
|
||||
|
||||
//查询数据
|
||||
export function queryReportService(LabReportInstr: Object){
|
||||
return request({
|
||||
url: '/labReportinstr/query',
|
||||
method: 'get',
|
||||
params: LabReportInstr
|
||||
})
|
||||
}
|
||||
|
||||
//修改数据
|
||||
export function updateReportService(LabReportInstr: Object){
|
||||
return request({
|
||||
url: '/labReportinstr/update',
|
||||
method: 'post',
|
||||
data: LabReportInstr
|
||||
})
|
||||
}
|
||||
|
||||
//删除数据
|
||||
export function deleteReportService(LabReportInstr: Object){
|
||||
return request({
|
||||
url: '/labReportinstr/del',
|
||||
method: 'get',
|
||||
params: LabReportInstr
|
||||
})
|
||||
}
|
||||
83
src/api/liswork/xtwh/StatsparameterApi.ts
Normal file
@ -0,0 +1,83 @@
|
||||
//参数设置字典
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function liststatsparam(params: any) {
|
||||
return request({
|
||||
url: '/statstemp/param/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典详细
|
||||
export function getstatsparam(id: number) {
|
||||
return request({
|
||||
url: `/statstemp/param/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addstatsparam(params: any) {
|
||||
return request({
|
||||
url: '/statstemp/param',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updatestatsparam(params: any) {
|
||||
return request({
|
||||
url: '/statstemp/param',
|
||||
method: 'put',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典
|
||||
export function delstatsparam(id: any) {
|
||||
return request({
|
||||
url: `/statstemp/param/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取模板详细信息
|
||||
export function getstatsTemplate(params: any) {
|
||||
return request({
|
||||
url: '/stats/gettemplate',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 模板参数查询详细信息
|
||||
export function getstatsQuery(params: any) {
|
||||
return request({
|
||||
url: '/stats/query',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
// 打印模板数据
|
||||
export function printTemplate(params: any) {
|
||||
return request({
|
||||
url: '/stats/print',
|
||||
method: 'post',
|
||||
data: params,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
// 导出excel
|
||||
export function exportTemplate(params: any) {
|
||||
return request({
|
||||
url: '/stats/exportExcel',
|
||||
method: 'post',
|
||||
data: params,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
55
src/api/liswork/xtwh/StatstemplateApi.ts
Normal file
@ -0,0 +1,55 @@
|
||||
//参数设置字典
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function liststatstemp(params: any) {
|
||||
return request({
|
||||
url: '/statstemp/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
// 复制模板
|
||||
export function copyParameter(params: any) {
|
||||
return request({
|
||||
url: '/statstemp/param/copyparameter',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典详细
|
||||
export function getstatstemp(id: number) {
|
||||
return request({
|
||||
url: `/statstemp/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addstatstemp(params: any) {
|
||||
return request({
|
||||
url: '/statstemp',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updatestatstemp(params: any) {
|
||||
return request({
|
||||
url: '/statstemp',
|
||||
method: 'put',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典
|
||||
export function delstatstemp(id: any) {
|
||||
return request({
|
||||
url: `/statstemp/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
46
src/api/liswork/xtwh/configdictApi.ts
Normal file
@ -0,0 +1,46 @@
|
||||
//参数设置字典
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function listconfigdict(params:any) {
|
||||
return request({
|
||||
url: '/configdict/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典详细
|
||||
export function getconfigdict(id:number) {
|
||||
return request({
|
||||
url: `/configdict/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addconfigdict(params:any) {
|
||||
return request({
|
||||
url: '/configdict',
|
||||
method: 'post',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updateconfigdict(params:any) {
|
||||
return request({
|
||||
url: '/configdict',
|
||||
method: 'put',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典
|
||||
export function delconfigdict(id:any) {
|
||||
return request({
|
||||
url: `/configdict/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
45
src/api/liswork/xtwh/localconfigApi.ts
Normal file
@ -0,0 +1,45 @@
|
||||
//本地参数设置
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function listlocalconfig(params:any) {
|
||||
return request({
|
||||
url: '/localconfig/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
export function getLocalConfigDefault(params:any) {
|
||||
return request({
|
||||
url: '/localconfig/resetdef',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典下拉框内容
|
||||
export function getoptionselect(params:any) {
|
||||
return request({
|
||||
url: '/localconfig/optionselect',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
// 修改字典
|
||||
export function updatelocalconfig(params:any) {
|
||||
return request({
|
||||
url: '/localconfig',
|
||||
method: 'put',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
// 批量保存所有结果
|
||||
export function savelocalconfig(params:any) {
|
||||
return request({
|
||||
url: '/localconfig/editall',
|
||||
method: 'put',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
63
src/api/liswork/xtwh/reportdictApi.ts
Normal file
@ -0,0 +1,63 @@
|
||||
//参数设置字典
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function listreportdict(params:any) {
|
||||
return request({
|
||||
url: '/reportdict/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典详细
|
||||
export function getreportdict(id:number) {
|
||||
return request({
|
||||
url: `/reportdict/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addreportdict(params:any) {
|
||||
return request({
|
||||
url: '/reportdict',
|
||||
method: 'post',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updatereportdict(params:any) {
|
||||
return request({
|
||||
url: '/reportdict',
|
||||
method: 'put',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典
|
||||
export function delreportdict(id:any) {
|
||||
return request({
|
||||
url: `/reportdict/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
|
||||
}
|
||||
// 自动加载
|
||||
export function autoload() {
|
||||
return request({
|
||||
url: '/reportdict/autoload',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典列表
|
||||
export function optionselect(params:any) {
|
||||
return request({
|
||||
url: '/reportdict/optionselect',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
47
src/api/liswork/xtwh/reportinstrApi.ts
Normal file
@ -0,0 +1,47 @@
|
||||
//参数设置字典
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function listreportinstr(params:any) {
|
||||
return request({
|
||||
url: '/reportinstr/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典详细
|
||||
export function getreportinstr(id:number) {
|
||||
return request({
|
||||
url: `/reportinstr/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addreportinstr(params:any) {
|
||||
return request({
|
||||
url: '/reportinstr',
|
||||
method: 'post',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updatereportinstr(params:any) {
|
||||
return request({
|
||||
url: '/reportinstr',
|
||||
method: 'put',
|
||||
data:params
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典
|
||||
export function delreportinstr(id:any) {
|
||||
return request({
|
||||
url: `/reportinstr/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
|
||||
}
|
||||
39
src/api/liswork/xtwh/xmFeeinstrApi.ts
Normal file
@ -0,0 +1,39 @@
|
||||
//仪器收费项目对照
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
//查询已分配数据
|
||||
export function queryService(params:any){
|
||||
return request({
|
||||
url: '/feeinstr/query',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//查询未分配的项目数据
|
||||
export function queryXmService(params:any){
|
||||
return request({
|
||||
url: '/feeinstr/queryXm',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//新增数据
|
||||
export function addService(params:any){
|
||||
return request({
|
||||
url: '/feeinstr/add',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//删除数据
|
||||
export function delService(params:any){
|
||||
return request({
|
||||
url: '/feeinstr/del',
|
||||
method: 'delete',
|
||||
params
|
||||
})
|
||||
}
|
||||
54
src/api/liswork/xtwh/xmReqItemVsApi.ts
Normal file
@ -0,0 +1,54 @@
|
||||
//收费项目报告项目对照
|
||||
// @ts-ignore
|
||||
import request from "@/utils/request";
|
||||
|
||||
//查询申请信息列表
|
||||
export function queryListService(params: any) {
|
||||
return request({
|
||||
url: "/vsReportitem/queryList",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
//查询项目明细
|
||||
export function queryDetailService(params: any) {
|
||||
return request({
|
||||
url: "/vsReportitem/query",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
//查询项目明细 old
|
||||
export function queryOldxminfo(params: any) {
|
||||
return request({
|
||||
url: "/oldxminfo/query",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
//搜索项目
|
||||
export function searchxminfo(params: any) {
|
||||
return request({
|
||||
url: "/vsReportitem/search",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
//添加收费项目报告项目对照
|
||||
export function addXminfo(data: Object) {
|
||||
return request({
|
||||
url: "/vsReportitem/add",
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
//删除收费项目报告项目对照
|
||||
export function delXminfo(data: Object) {
|
||||
return request({
|
||||
url: "/vsReportitem/del",
|
||||
method: "delete",
|
||||
params: data,
|
||||
});
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 登录方法
|
||||
export function login(username, password, code, uuid) {
|
||||
export function login(username, password, code, uuid,loginParam) {
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
uuid
|
||||
uuid,
|
||||
loginParam
|
||||
}
|
||||
return request({
|
||||
url: '/login',
|
||||
@ -19,6 +20,26 @@ export function login(username, password, code, uuid) {
|
||||
})
|
||||
}
|
||||
|
||||
// 单点登录
|
||||
export function loginAnonymous(data) {
|
||||
return request({
|
||||
url: '/loginAnonymous',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function getLocalconfig(data) {
|
||||
return request({
|
||||
url: '/getLocalconfig',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get',
|
||||
params: data,
|
||||
timeout: 20000
|
||||
})
|
||||
}
|
||||
// 注册方法
|
||||
export function register(data) {
|
||||
return request({
|
||||
|
||||
@ -23,18 +23,18 @@ export function printBarcodeall(data) {
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 查询采样登记详细
|
||||
export function getReqmain(sqh) {
|
||||
// 查询病人列表
|
||||
export function queryPatList() {
|
||||
return request({
|
||||
url: '/system/reqmain/' + sqh,
|
||||
url: '/mzcx/queryPatList',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增采样登记
|
||||
export function addReqmain(data) {
|
||||
// 打印回单
|
||||
export function printBackpaper(data) {
|
||||
return request({
|
||||
url: '/system/reqmain',
|
||||
url: '/mzcx/printBackpaper',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
|
||||
155
src/api/mzcx/index.ts
Normal file
@ -0,0 +1,155 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
|
||||
// 查询条码类别
|
||||
export function feeitemclassList(query?: Object) {
|
||||
return request({
|
||||
url: 'feeitemclass/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 报告领取规则
|
||||
export function rptgetrules(query?: Object) {
|
||||
return request({
|
||||
url: '/rptgetrule/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 新增条码类别
|
||||
export function feeitemclassAdd(query?: Object) {
|
||||
return request({
|
||||
url: '/feeitemclass/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 修改条码类别
|
||||
export function feeitemclassUpdate(query?: Object) {
|
||||
return request({
|
||||
url: '/feeitemclass/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 删除条码类别
|
||||
export function feeitemclassDel(query?: Object) {
|
||||
return request({
|
||||
url: '/feeitemclass/del',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 收费项目维护列表
|
||||
export function xmfeeList(query?: Object) {
|
||||
return request({
|
||||
url: 'xmfee/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 收费项目新增
|
||||
export function xmfeeadd(query?: Object) {
|
||||
return request({
|
||||
url: 'xmfee/addXmfee',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 收费项目修改
|
||||
export function xmfeeUpdate(query?: Object) {
|
||||
return request({
|
||||
url: 'xmfee/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 收费项目删除
|
||||
export function xmfeeDel(query?: Object) {
|
||||
return request({
|
||||
url: 'xmfee/del',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 报告领取规则维护列表
|
||||
export function rptgetruleList(query?: Object) {
|
||||
return request({
|
||||
url: 'rptgetrule/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 报告领取规则明细列表
|
||||
export function rptgetruleDetail(query?: Object) {
|
||||
return request({
|
||||
url: 'rptgetrule/queryDetail',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 报告领取规则新增
|
||||
export function rptgetruleadd(query?: Object) {
|
||||
return request({
|
||||
url: 'rptgetrule/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 报告领取规则修改
|
||||
export function rptgetruleUpdate(query?: Object) {
|
||||
return request({
|
||||
url: 'rptgetrule/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 报告领取规则删除
|
||||
export function rptgetruleDel(query?: Object) {
|
||||
return request({
|
||||
url: 'rptgetrule/del',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 报告领取规则明细删除
|
||||
export function rptgetruleDelDetail(query?: Object) {
|
||||
return request({
|
||||
url: 'rptgetrule/delDetail',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询条码类别与项目对照
|
||||
export function feeitemvsList(query?: Object) {
|
||||
return request({
|
||||
url: '/feeitemvsclass/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 保存对照的项目
|
||||
export function feeitemvAdd(query?: Object) {
|
||||
return request({
|
||||
url: '/feeitemvsclass/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 保存对照的项目
|
||||
export function feeitemvDel(query?: Object) {
|
||||
return request({
|
||||
url: '/feeitemvsclass/del',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
// pinyin.js - 拼音转换工具
|
||||
// src/utils/pinyin-utils.js
|
||||
import { pinyin } from 'pinyin-pro';
|
||||
|
||||
/**
|
||||
* 获取文本的拼音首字母
|
||||
* @param {string} text - 要转换的文本
|
||||
* @returns {string} - 拼音首字母字符串
|
||||
*/
|
||||
export function getFirstLetter(text) {
|
||||
if (!text) return '';
|
||||
|
||||
// 获取拼音(不带音调,数组形式)
|
||||
const pinyinArray = pinyin(text, { toneType: "none", type: "array" });
|
||||
|
||||
// 提取每个拼音的首字母并连接
|
||||
return pinyinArray.map(word => word.charAt(0)).join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本的拼音全拼
|
||||
* @param {string} text - 要转换的文本
|
||||
* @returns {string} - 拼音全拼字符串
|
||||
*/
|
||||
export function getFullPinyin(text) {
|
||||
if (!text) return '';
|
||||
|
||||
// 获取拼音(不带音调,字符串形式)
|
||||
return pinyin(text, { toneType: "none" }).replace(/\s+/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理选项数据,添加拼音和首字母属性
|
||||
* @param {Array} options - 原始选项数组,每个元素包含id和text属性
|
||||
* @returns {Array} - 处理后的选项数组,每个元素包含pinyin和firstLetters属性
|
||||
*/
|
||||
export function processOptions(options) {
|
||||
return options.map(option => ({
|
||||
...option,
|
||||
pinyin: getFullPinyin(option.text),
|
||||
firstLetters: getFirstLetter(option.text)
|
||||
}));
|
||||
}
|
||||
44
src/api/regional/dict/diagnosis.js
Normal file
@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询诊断列表
|
||||
export function listdiagnosis(query) {
|
||||
return request({
|
||||
url: '/transitdict/diagnosis/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询诊断详细
|
||||
export function getdiagnosis(diagnosisId) {
|
||||
return request({
|
||||
url: '/transitdict/diagnosis/' + diagnosisId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增诊断
|
||||
export function adddiagnosis(data) {
|
||||
return request({
|
||||
url: '/transitdict/diagnosis',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改诊断
|
||||
export function updatediagnosis(data) {
|
||||
return request({
|
||||
url: '/transitdict/diagnosis',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除诊断
|
||||
export function deldiagnosis(diagnosisId) {
|
||||
return request({
|
||||
url: '/transitdict/diagnosis/' + diagnosisId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
44
src/api/regional/dict/hospital.js
Normal file
@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询医疗机构列表
|
||||
export function listhospital(query) {
|
||||
return request({
|
||||
url: '/transitdict/hospital/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询医疗机构详细
|
||||
export function gethospital(hospitalId) {
|
||||
return request({
|
||||
url: '/transitdict/hospital/' + hospitalId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增医疗机构
|
||||
export function addhospital(data) {
|
||||
return request({
|
||||
url: '/transitdict/hospital',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改医疗机构
|
||||
export function updatehospital(data) {
|
||||
return request({
|
||||
url: '/transitdict/hospital',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除医疗机构
|
||||
export function delhospital(hospitalId) {
|
||||
return request({
|
||||
url: '/transitdict/hospital/' + hospitalId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
44
src/api/regional/dict/itemclass.js
Normal file
@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询诊断列表
|
||||
export function listitemclass(query) {
|
||||
return request({
|
||||
url: '/transitdict/itemclass/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询诊断详细
|
||||
export function getitemclass(itemclassId) {
|
||||
return request({
|
||||
url: '/transitdict/itemclass/' + itemclassId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增诊断
|
||||
export function additemclass(data) {
|
||||
return request({
|
||||
url: '/transitdict/itemclass',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改诊断
|
||||
export function updateitemclass(data) {
|
||||
return request({
|
||||
url: '/transitdict/itemclass',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除诊断
|
||||
export function delitemclass(itemclassId) {
|
||||
return request({
|
||||
url: '/transitdict/itemclass/' + itemclassId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
44
src/api/regional/dict/regdict.js
Normal file
@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询字典列表
|
||||
export function listregdict(query) {
|
||||
return request({
|
||||
url: '/transitdict/regdict/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询字典详细
|
||||
export function getregdict(regdictId) {
|
||||
return request({
|
||||
url: '/transitdict/regdict/' + regdictId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addregdict(data) {
|
||||
return request({
|
||||
url: '/transitdict/regdict',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updateregdict(data) {
|
||||
return request({
|
||||
url: '/transitdict/regdict',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除字典
|
||||
export function delregdict(regdictId) {
|
||||
return request({
|
||||
url: '/transitdict/regdict/' + regdictId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
59
src/api/regional/index.ts
Normal file
@ -0,0 +1,59 @@
|
||||
// @ts-ignore
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取流转数据
|
||||
export function querySample(query?: Object) {
|
||||
return request({
|
||||
url: '/transit/querySample',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 获取未签收的标本
|
||||
export function querySampleSign(query?: Object) {
|
||||
return request({
|
||||
url: '/transit/querySampleSign',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 签收标本
|
||||
export function sampleSign(query?: Object) {
|
||||
return request({
|
||||
url: '/transit/sampleSign',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
}
|
||||
// 退回的标本
|
||||
export function querySampleSignBack(query?: Object) {
|
||||
return request({
|
||||
url: '/transit/querySampleSignBack',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 标本报表
|
||||
export function sampleTypeCount(query?: Object) {
|
||||
return request({
|
||||
url: '/transitReport/sampleTypeCount',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 标本报表费用
|
||||
export function sampleitemCount(query?: Object) {
|
||||
return request({
|
||||
url: '/transitReport/itemCount',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 标本报表费用
|
||||
export function getallcount(query?: Object) {
|
||||
return request({
|
||||
url: '/transitstat/getallcount',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
53
src/api/system/parameter.ts
Normal file
@ -0,0 +1,53 @@
|
||||
//@ts-ignore js语法检查忽略
|
||||
import request from '@/utils/request';
|
||||
|
||||
|
||||
// 查询参数列表
|
||||
export function paramList(query?: Object) {
|
||||
return request({
|
||||
url: '/param/query',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 新增参数列表
|
||||
export function addParam(query?: Object) {
|
||||
return request({
|
||||
url: '/param/add',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 修改参数列表
|
||||
export function updateParam(query?: Object) {
|
||||
return request({
|
||||
url: '/param/update',
|
||||
method: 'post',
|
||||
data: query,
|
||||
});
|
||||
}
|
||||
// 删除参数列表
|
||||
export function delParam(query?: Object) {
|
||||
return request({
|
||||
url: '/param/del',
|
||||
method: 'delete',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
// 查询参数列表树状结构
|
||||
export function paramTree(query?: Object) {
|
||||
return request({
|
||||
url: '/param/queryTree',
|
||||
method: 'get',
|
||||
params: query,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询某个参数
|
||||
export function queryOneService(yq: string,xxdh: string) {
|
||||
return request({
|
||||
url: '/param/queryOne',
|
||||
method: 'get',
|
||||
params: {yq,xxdh}
|
||||
});
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
import {
|
||||
parseStrEmpty
|
||||
} from "@/utils/ruoyi";
|
||||
|
||||
// 查询用户列表
|
||||
export function listUser(query) {
|
||||
@ -133,3 +135,20 @@ export function deptTreeSelect() {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 从老lis系统导入
|
||||
export function importFromLis() {
|
||||
return request({
|
||||
url: '/system/user/syncUser',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// 获取登录用户姓名
|
||||
export function getUserName(data) {
|
||||
return request({
|
||||
url: '/system/role/getUserName',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
1
src/assets/icons/svg/hongcha.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M436.288 512L144.064 219.84a53.696 53.696 0 0 1 75.776-75.968l292.48 292.48 292.224-292.48a53.696 53.696 0 1 1 75.968 75.968L588.288 512.064l292.224 292.416a53.696 53.696 0 0 1-75.968 75.776L512.256 588.032l-292.416 292.224a53.44 53.44 0 0 1-75.776 0 53.44 53.44 0 0 1 0-75.776L436.288 512z" fill="#FC2530" /></svg>
|
||||
|
After Width: | Height: | Size: 582 B |
1
src/assets/icons/svg/lvgou.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="171.52px" viewBox="0 0 1194 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M1135.018667 99.84c-29.525333-22.442667-61.952-18.773333-84.992 10.24L469.162667 705.792 151.552 418.56l-5.632-6.229333c-24.064-23.04-56.234667-20.906667-83.370667 0-29.525333 22.698667-23.296 52.906667 0 81.578666l306.005334 394.24 7.168 8.277334a138.24 138.24 0 0 0 183.637333 13.653333c8.618667-6.656 16.384-14.336 23.210667-22.869333l547.669333-704.170667 4.778667-6.826667c17.237333-28.501333 27.477333-55.466667 0-76.202666V99.84z" fill="#009269" /></svg>
|
||||
|
After Width: | Height: | Size: 728 B |
BIN
src/assets/images/bg2.jpg
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
src/assets/images/border_bg.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/images/login_left.png
Normal file
|
After Width: | Height: | Size: 473 KiB |
BIN
src/assets/images/logo_new.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 6.7 KiB |
BIN
src/assets/images/title_border_bg.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/images/title_left_bg.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
src/assets/images/title_right_bg.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/assets/images/xjt.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
src/assets/images/yjt.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 134 KiB |
@ -97,3 +97,19 @@
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
.btn_green {
|
||||
background-color: #aef5ef !important;
|
||||
color: #148A7F;
|
||||
border-color: #aef5ef;
|
||||
}
|
||||
|
||||
.btns_box {
|
||||
padding: .3125rem .625rem !important;
|
||||
font-size: .875rem;
|
||||
height: 1.25rem !important;
|
||||
margin: 5px 0;
|
||||
margin-left: .625rem !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
@ -123,7 +123,10 @@ aside {
|
||||
|
||||
//main-container全局样式
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
padding: 10px 10px 0 10px;
|
||||
height: calc(100vh - 5.25rem);
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.07);
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.components-container {
|
||||
@ -132,7 +135,7 @@ aside {
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 30px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
@ -173,6 +176,32 @@ aside {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.compact-form {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.el-form-item__label {
|
||||
padding-bottom: 0px;
|
||||
color: #08355E;
|
||||
font-size: .75rem;
|
||||
}
|
||||
|
||||
// pointer-events: none;
|
||||
|
||||
:deep(.el-radio__label) {
|
||||
color: #08355E;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
padding-bottom: 10px;
|
||||
|
||||
@ -182,3 +211,306 @@ aside {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.flex-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
.time-line-box {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
margin-top: .35rem;
|
||||
background-color: #f0f3f8;
|
||||
padding: .3rem 2.5rem;
|
||||
|
||||
|
||||
.time-line-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
width: 16.6%;
|
||||
|
||||
.timeline-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.index {
|
||||
width: 1.875rem;
|
||||
height: 1.875rem;
|
||||
line-height: 1.875rem;
|
||||
background: #E1E9F7;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
font-weight: 500;
|
||||
font-size: 1.125rem;
|
||||
color: #4767A3;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: #4096ff;
|
||||
box-shadow: 0 0 0 .25rem rgba(64, 150, 255, 0.2);
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.timeline-title {
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
color: #4767A3;
|
||||
}
|
||||
|
||||
.timeline-time {
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
font-weight: 400;
|
||||
font-size: .875rem;
|
||||
color: #4767A3;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.no_active {
|
||||
|
||||
.index,
|
||||
.timeline-title {
|
||||
color: #9b9999 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.timg {
|
||||
width: 3.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.next_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.jt_btn {
|
||||
width: 1.5rem;
|
||||
height: 2rem;
|
||||
line-height: 2rem;
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
background-color: #1f6dd3;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.next_btn {
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.search-form {
|
||||
:deep(.el-form-item__label) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.el-form-item--default {
|
||||
margin-bottom: .3125rem !important;
|
||||
}
|
||||
|
||||
.el-form-item--small {
|
||||
margin-bottom: .3125rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.page-box {
|
||||
margin-top: 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
.tabs_box {
|
||||
.el-tabs__header {
|
||||
height: 1.875rem !important;
|
||||
margin-bottom: 0px;
|
||||
font-size: .875rem;
|
||||
|
||||
.el-tabs__item {
|
||||
height: 1.875rem !important;
|
||||
padding: 0 .625rem;
|
||||
|
||||
&.is-active {
|
||||
border-bottom: .125rem solid #409eff !important;
|
||||
background-color: #e9f1fb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-tabs__nav-next,
|
||||
.el-tabs__nav-prev {
|
||||
line-height: 1.875rem;
|
||||
color: #1f6dd3;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
.el-tree-node__children {
|
||||
padding-left: 15px !important;
|
||||
}
|
||||
|
||||
|
||||
/* 禁止文本选中 */
|
||||
.no-select {
|
||||
user-select: none;
|
||||
/* 兼容旧版浏览器 */
|
||||
-webkit-user-select: none;
|
||||
/* Safari/Chrome */
|
||||
-moz-user-select: none;
|
||||
/* Firefox */
|
||||
-ms-user-select: none;
|
||||
/* IE/Edge */
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.query-form {
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bb_table {
|
||||
.vxe-table.border--full {
|
||||
border: 1px solid #ccc !important;
|
||||
|
||||
.vxe-header--column,
|
||||
.vxe-body--column,
|
||||
.vxe-footer--column {
|
||||
border-right: 1px solid #ccc !important;
|
||||
border-bottom: 1px solid #ccc !important;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 !important;
|
||||
background-image: none !important;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.vxe-footer--column {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* 表头最下方单元格强制底红线 */
|
||||
.vxe-header--row:last-of-type .vxe-header--column {
|
||||
border-bottom: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
.vxe-body--row {
|
||||
border-bottom: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
.vxe-footer--row.vxe-footer--row {
|
||||
border-top: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
.vxe-header--row th {
|
||||
height: 30px !important;
|
||||
line-height: 30px;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.vxe-body--row td {
|
||||
height: 30px !important;
|
||||
line-height: 30px;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
.vxe-footer--row td {
|
||||
height: 30px !important;
|
||||
line-height: 30px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* 清除最后一列重复竖线,避免双线重叠 */
|
||||
.vxe-header--col:last-child .vxe-header--column,
|
||||
.vxe-body--col:last-child .vxe-body--column,
|
||||
.vxe-footer--col:last-child .vxe-footer--column {
|
||||
border-right: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.vxe-table--render-default .vxe-table--footer-wrapper {
|
||||
border-top: 1px solid #ccc !important;
|
||||
}
|
||||
|
||||
.vxe-table--header-wrapper {
|
||||
border-bottom: 1px solid #ccc !important;
|
||||
background-color: #eff6fa !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.el-input.is-disabled .el-input__wrapper {
|
||||
background-color: #dee1e5 !important;
|
||||
}
|
||||
|
||||
.el-select__wrapper.is-disabled {
|
||||
background-color: #dee1e5 !important;
|
||||
}
|
||||
|
||||
.el-select__wrapper.is-disabled .el-select__selected-item {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
||||
.el-date-editor.is-disabled,
|
||||
.el-date-editor.is-disabled .el-input__wrapper {
|
||||
background-color: #dee1e5 !important;
|
||||
}
|
||||
|
||||
.el-radio__input.is-disabled+span.el-radio__label,
|
||||
.el-checkbox.is-disabled {
|
||||
color: #606266 !important;
|
||||
}
|
||||
|
||||
.el-radio__input.is-disabled.is-checked .el-radio__inner {
|
||||
background: #1f6dd3;
|
||||
border-color: #1f6dd3;
|
||||
|
||||
&::after {
|
||||
background: #dee1e5;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
|
||||
background: #00a5ff;
|
||||
|
||||
&::after {
|
||||
border-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.el-checkbox__input.is-disabled+span.el-checkbox__label {
|
||||
color: #606266 !important;
|
||||
}
|
||||
@ -4,278 +4,642 @@
|
||||
*/
|
||||
|
||||
/** 基础通用 **/
|
||||
.pt5 {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.pr5 {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.pb5 {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.mt5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.mr5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.mb5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.ml5 {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mb10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.mr20 {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.ml20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.pt5 {
|
||||
padding-top: .3125rem;
|
||||
}
|
||||
|
||||
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
.pr5 {
|
||||
padding-right: .3125rem;
|
||||
}
|
||||
|
||||
.el-form .el-form-item__label {
|
||||
font-weight: 700;
|
||||
}
|
||||
.el-dialog:not(.is-fullscreen) {
|
||||
margin-top: 6vh !important;
|
||||
}
|
||||
.pb5 {
|
||||
padding-bottom: .3125rem;
|
||||
}
|
||||
|
||||
.el-dialog.scrollbar .el-dialog__body {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 70vh;
|
||||
padding: 10px 20px 0;
|
||||
}
|
||||
.mt5 {
|
||||
margin-top: .3125rem;
|
||||
}
|
||||
|
||||
.el-table {
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9 !important;
|
||||
color: #515a6e;
|
||||
height: 40px !important;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.el-table__body-wrapper {
|
||||
.el-button [class*="el-icon-"] + span {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mr5 {
|
||||
margin-right: .3125rem;
|
||||
}
|
||||
|
||||
/** 表单布局 **/
|
||||
.form-header {
|
||||
font-size:15px;
|
||||
color:#6379bb;
|
||||
border-bottom:1px solid #ddd;
|
||||
margin:8px 10px 25px 10px;
|
||||
padding-bottom:5px
|
||||
}
|
||||
.mb5 {
|
||||
margin-bottom: .3125rem;
|
||||
}
|
||||
|
||||
/** 表格布局 **/
|
||||
.pagination-container {
|
||||
position: relative;
|
||||
height: 25px;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 15px;
|
||||
padding: 10px 20px !important;
|
||||
}
|
||||
.mb8 {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.el-dialog .pagination-container {
|
||||
position: static !important;
|
||||
}
|
||||
.ml5 {
|
||||
margin-left: .3125rem;
|
||||
}
|
||||
|
||||
/* tree border */
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #FFFFFF none;
|
||||
border-radius:4px;
|
||||
width: 100%;
|
||||
}
|
||||
.mt10 {
|
||||
margin-top: .625rem;
|
||||
}
|
||||
|
||||
.pagination-container .el-pagination {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: .625rem;
|
||||
}
|
||||
|
||||
@media ( max-width : 768px) {
|
||||
.pagination-container .el-pagination > .el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.mb10 {
|
||||
margin-bottom: .625rem;
|
||||
}
|
||||
|
||||
.el-table .fixed-width .el-button--small {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: inherit;
|
||||
}
|
||||
.ml10 {
|
||||
margin-left: .625rem;
|
||||
}
|
||||
|
||||
/** 表格更多操作下拉样式 */
|
||||
.el-table .el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
.mr20 {
|
||||
margin-right: 1.25rem;
|
||||
}
|
||||
|
||||
.el-tree-node__content > .el-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.mb20 {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.list-group-striped > .list-group-item {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.ml20 {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
.cp {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.h1,
|
||||
.h2,
|
||||
.h3,
|
||||
.h4,
|
||||
.h5,
|
||||
.h6,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.el-card__header {
|
||||
padding: 14px 15px 7px !important;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.el-card__body {
|
||||
padding: 15px 20px 20px 20px !important;
|
||||
}
|
||||
.el-form--inline .el-form-item {
|
||||
margin-right: .9375rem;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.el-form-item__label {
|
||||
// font-weight: 700;
|
||||
// font-size: 14px;
|
||||
color: #08355E;
|
||||
}
|
||||
|
||||
/* button color */
|
||||
.el-button--cyan.is-active,
|
||||
.el-button--cyan:active {
|
||||
background: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.el-dialog:not(.is-fullscreen) {
|
||||
margin-top: 6vh !important;
|
||||
padding: 0;
|
||||
// border-radius: 20px;
|
||||
|
||||
.el-button--cyan:focus,
|
||||
.el-button--cyan:hover {
|
||||
background: #48D1CC;
|
||||
border-color: #48D1CC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button--cyan {
|
||||
background-color: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.el-dialog.scrollbar .el-dialog__body {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 70vh;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
/* text color */
|
||||
.text-navy {
|
||||
color: #1ab394;
|
||||
}
|
||||
.el-dialog__header {
|
||||
background: linear-gradient(90deg, #0c1a97 0%, #1373d3 100%);
|
||||
padding: 10px 20px;
|
||||
position: relative;
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
|
||||
.text-primary {
|
||||
color: inherit;
|
||||
}
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: url('@/assets/logo/logo.png') no-repeat center;
|
||||
background-size: contain;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #1c84c6;
|
||||
}
|
||||
// 标题文本样式
|
||||
.el-dialog__title {
|
||||
color: #fff;
|
||||
/* 标题文字颜色 */
|
||||
padding-left: 40px;
|
||||
/* 给 Logo 留出空间 */
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #23c6c8;
|
||||
}
|
||||
.el-dialog__headerbtn .el-dialog__close {
|
||||
color: #fff;
|
||||
/* 关闭按钮颜色 */
|
||||
font-size: 18px;
|
||||
|
||||
.text-warning {
|
||||
color: #f8ac59;
|
||||
}
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #ed5565;
|
||||
}
|
||||
.el-dialog__footer {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #888888;
|
||||
}
|
||||
.el-table {
|
||||
padding: 0 !important;
|
||||
border-radius: .625rem !important;
|
||||
|
||||
/* image */
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.el-table__header-wrapper,
|
||||
.el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #1F6DD3 !important;
|
||||
color: #FFF;
|
||||
height: 1.875rem !important;
|
||||
font-size: .8125rem;
|
||||
}
|
||||
}
|
||||
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.el-table__body-wrapper {
|
||||
.el-button [class*="el-icon-"]+span {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-upload-preview {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-table__body td {
|
||||
font-size: .8125rem;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* 拖拽列样式 */
|
||||
.sortable-ghost{
|
||||
opacity: .8;
|
||||
color: #fff!important;
|
||||
background: #42b983!important;
|
||||
}
|
||||
|
||||
/* 表格右侧工具栏样式 */
|
||||
.top-right-btn {
|
||||
margin-left: auto;
|
||||
}
|
||||
/* 表格最外层边框(可选) */
|
||||
.el-table--border {
|
||||
border: 1px solid #1F6DD3 !important;
|
||||
}
|
||||
|
||||
.el-scrollbar__bar.is-vertical {
|
||||
right: 0;
|
||||
width: 9px !important;
|
||||
}
|
||||
|
||||
.el-scrollbar__bar.is-horizontal {
|
||||
height: 8px !important;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.el-scrollbar__thumb {
|
||||
background-color: #817e7e !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.el-scrollbar__thumb:hover {
|
||||
background-color: #817e7e !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cell.el-tooltip {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.el-table__body-wrapper .el-table-column--selection>.cell {
|
||||
padding: 0 !important;
|
||||
height: 1.8125rem;
|
||||
line-height: 1.8125rem;
|
||||
}
|
||||
|
||||
.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell {
|
||||
background-color: #a4beef !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.cell.el-tooltip {
|
||||
padding: 0 !important;
|
||||
height: 1.8125rem;
|
||||
line-height: 1.8125rem;
|
||||
}
|
||||
|
||||
.el-table-header-cell .cell {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.el-table--default {
|
||||
.cell {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.el-table__cell {
|
||||
padding: 0 !important;
|
||||
height: 1.8125rem;
|
||||
line-height: 1.8125rem;
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
/* 修改选中行背景色 */
|
||||
.el-table__body tr.current-row>td {
|
||||
background-color: #a4beef !important;
|
||||
}
|
||||
|
||||
// /* 可选:修改悬停颜色 */
|
||||
// .el-table__body tr.hover-row>td {
|
||||
// background-color: #a4beef !important;
|
||||
// }
|
||||
|
||||
.el-table__empty-block {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table--border {
|
||||
border: 1px solid #96B8D9 !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
.el-table td.el-table__cell,
|
||||
.el-table th.el-table__cell.is-leaf {
|
||||
border-bottom: 1px solid #96B8D9 !important;
|
||||
}
|
||||
|
||||
.el-table--border .el-table__cell {
|
||||
border-right: 1px solid #96B8D9 !important;
|
||||
}
|
||||
|
||||
/* 表格内部边框(可选) */
|
||||
.el-table--border th.el-table__cell {
|
||||
border-right: 1px solid #1F6DD3 !important;
|
||||
}
|
||||
|
||||
.el-input__wrapper,
|
||||
.el-select__wrapper {
|
||||
box-shadow: 0 0 0 1px #96B8D9 inset;
|
||||
|
||||
.is-focus {
|
||||
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.el-select__wrapper.is-disabled {
|
||||
background-color: #dfdcdc !important;
|
||||
}
|
||||
|
||||
.el-select-dropdown__item.is-hovering {
|
||||
background-color: #a4beef !important;
|
||||
}
|
||||
|
||||
.el-input.is-disabled .el-input__wrapper {
|
||||
background-color: #dfdcdc !important;
|
||||
}
|
||||
|
||||
.el-input.is-disabled .el-input__inner {
|
||||
-webkit-text-fill-color: #4e4c4c;
|
||||
}
|
||||
|
||||
|
||||
.el-date-editor.el-input__wrapper {
|
||||
box-shadow: 0 0 0 1px #96B8D9 inset;
|
||||
|
||||
.is-focus {
|
||||
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 1px #1f6dd3 inset !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.mytable-style {
|
||||
.vxe-table {
|
||||
border: 1px solid #96B8D9 !important;
|
||||
border-top: none !important;
|
||||
/* 蓝色外边框 */
|
||||
border-radius: .5rem;
|
||||
/* 可选:添加边框圆角 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vxe-header--column {
|
||||
word-break: break-word;
|
||||
background-color: #1F6DD3 !important;
|
||||
color: #FFF;
|
||||
height: 1.875rem !important;
|
||||
line-height: 1.875rem !important;
|
||||
padding: 0 !important;
|
||||
font-size: .8125rem;
|
||||
border-color: #1F6DD3 !important;
|
||||
}
|
||||
|
||||
.vxe-table--render-default.is--padding .vxe-body--column .vxe-cell {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.vxe-table--render-default .vxe-header--column .vxe-cell {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.vxe-table--render-default .vxe-body--column,
|
||||
.vxe-footer--column,
|
||||
.col--ellipsis {
|
||||
height: 1.875rem !important;
|
||||
line-height: 1.875rem !important;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
height: 1.875rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 高亮
|
||||
.vxe-table--render-default .vxe-body--row.row--current {
|
||||
background-color: #a4beef !important;
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.vxe-table--render-default .vxe-body--row.row--current .vxe-cell {
|
||||
background-color: #a4beef !important;
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
// 滚动条
|
||||
.vxe-table ::-webkit-scrollbar {
|
||||
width: .6rem;
|
||||
height: .5rem;
|
||||
}
|
||||
|
||||
.vxe-table ::-webkit-scrollbar-thumb {
|
||||
background-color: #817e7e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vxe-table ::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #817e7e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.el-table--default .cell {
|
||||
padding: 0 0 0 .3125rem !important;
|
||||
}
|
||||
|
||||
// 表格input宽度,表格select宽度
|
||||
.full-width-input .el-input__inner .el-select__inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.full-width-input {
|
||||
.el-input__wrapper {
|
||||
// box-shadow: 0 0 0 1px rgba(64, 158, 255, 0.2);
|
||||
box-shadow: none;
|
||||
background: transparent !important;
|
||||
padding: 0 !important;
|
||||
padding-left: .3125rem !important;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-select__wrapper {
|
||||
box-shadow: none;
|
||||
background: transparent !important;
|
||||
padding: 0 !important;
|
||||
padding-left: .3125rem !important;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 表单布局 **/
|
||||
.form-header {
|
||||
font-size: .9375rem;
|
||||
color: #6379bb;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: .5rem .625rem 1.5625rem .625rem;
|
||||
padding-bottom: 5px
|
||||
}
|
||||
|
||||
/** 表格布局 **/
|
||||
.pagination-container {
|
||||
position: relative;
|
||||
height: 50px;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 15px;
|
||||
padding: 10px 20px !important;
|
||||
}
|
||||
|
||||
.el-dialog .pagination-container {
|
||||
position: static !important;
|
||||
}
|
||||
|
||||
/* tree border */
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #FFFFFF none;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination-container .el-pagination {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media (max-width : 768px) {
|
||||
.pagination-container .el-pagination>.el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.pagination-container .el-pagination>.el-pagination__sizes {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table .fixed-width .el-button--small {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
/** 表格更多操作下拉样式 */
|
||||
.el-table .el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #1F6DD3;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.el-table .el-dropdown,
|
||||
.el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-tree-node__content>.el-checkbox {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.list-group-striped>.list-group-item {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.el-card__header {
|
||||
padding: 14px 15px 7px !important;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.el-card__body {
|
||||
padding: 15px 20px 20px 20px !important;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* button color */
|
||||
.el-button--cyan.is-active,
|
||||
.el-button--cyan:active {
|
||||
background: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan:focus,
|
||||
.el-button--cyan:hover {
|
||||
background: #48D1CC;
|
||||
border-color: #48D1CC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.el-button--cyan {
|
||||
background-color: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* text color */
|
||||
.text-navy {
|
||||
color: #1ab394;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #1c84c6;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #23c6c8;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #f8ac59;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #ed5565;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
/* image */
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.avatar-upload-preview {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 拖拽列样式 */
|
||||
.sortable-ghost {
|
||||
opacity: .8;
|
||||
color: #fff !important;
|
||||
background: #42b983 !important;
|
||||
}
|
||||
|
||||
/* 表格右侧工具栏样式 */
|
||||
.top-right-btn {
|
||||
margin-left: auto;
|
||||
}
|
||||
@ -36,7 +36,7 @@ $base-sub-menu-background:#000c17;
|
||||
$base-sub-menu-hover:#001528;
|
||||
*/
|
||||
|
||||
$--color-primary: #409EFF;
|
||||
$--color-primary: #1F6DD3;
|
||||
$--color-success: #67C23A;
|
||||
$--color-warning: #E6A23C;
|
||||
$--color-danger: #F56C6C;
|
||||
|
||||
87
src/auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createPinia: typeof import('pinia')['createPinia']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const defineStore: typeof import('pinia')['defineStore']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getActivePinia: typeof import('pinia')['getActivePinia']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const mapActions: typeof import('pinia')['mapActions']
|
||||
const mapGetters: typeof import('pinia')['mapGetters']
|
||||
const mapState: typeof import('pinia')['mapState']
|
||||
const mapStores: typeof import('pinia')['mapStores']
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const storeToRefs: typeof import('pinia')['storeToRefs']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
511
src/components/Ballpit/index.vue
Normal file
@ -0,0 +1,511 @@
|
||||
<script setup lang="ts">
|
||||
// @ts-ignore
|
||||
import { Clock, Mesh, OrthographicCamera, PlaneGeometry, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderer } from 'three';
|
||||
import { onBeforeUnmount, onMounted, ref, useTemplateRef, watch, type CSSProperties } from 'vue';
|
||||
|
||||
const vertexShader = `
|
||||
precision highp float;
|
||||
|
||||
void main() {
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const fragmentShader = `
|
||||
precision highp float;
|
||||
|
||||
uniform float iTime;
|
||||
uniform vec3 iResolution;
|
||||
uniform float animationSpeed;
|
||||
|
||||
uniform bool enableTop;
|
||||
uniform bool enableMiddle;
|
||||
uniform bool enableBottom;
|
||||
|
||||
uniform int topLineCount;
|
||||
uniform int middleLineCount;
|
||||
uniform int bottomLineCount;
|
||||
|
||||
uniform float topLineDistance;
|
||||
uniform float middleLineDistance;
|
||||
uniform float bottomLineDistance;
|
||||
|
||||
uniform vec3 topWavePosition;
|
||||
uniform vec3 middleWavePosition;
|
||||
uniform vec3 bottomWavePosition;
|
||||
|
||||
uniform vec2 iMouse;
|
||||
uniform bool interactive;
|
||||
uniform float bendRadius;
|
||||
uniform float bendStrength;
|
||||
uniform float bendInfluence;
|
||||
|
||||
uniform bool parallax;
|
||||
uniform float parallaxStrength;
|
||||
uniform vec2 parallaxOffset;
|
||||
|
||||
uniform vec3 lineGradient[8];
|
||||
uniform int lineGradientCount;
|
||||
|
||||
const vec3 BLACK = vec3(0.0);
|
||||
const vec3 PINK = vec3(233.0, 71.0, 245.0) / 255.0;
|
||||
const vec3 BLUE = vec3(47.0, 75.0, 162.0) / 255.0;
|
||||
|
||||
mat2 rotate(float r) {
|
||||
return mat2(cos(r), sin(r), -sin(r), cos(r));
|
||||
}
|
||||
|
||||
vec3 background_color(vec2 uv) {
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
float y = sin(uv.x - 0.2) * 0.3 - 0.1;
|
||||
float m = uv.y - y;
|
||||
|
||||
col += mix(BLUE, BLACK, smoothstep(0.0, 1.0, abs(m)));
|
||||
col += mix(PINK, BLACK, smoothstep(0.0, 1.0, abs(m - 0.8)));
|
||||
return col * 0.5;
|
||||
}
|
||||
|
||||
vec3 getLineColor(float t, vec3 baseColor) {
|
||||
if (lineGradientCount <= 0) {
|
||||
return baseColor;
|
||||
}
|
||||
|
||||
vec3 gradientColor;
|
||||
|
||||
if (lineGradientCount == 1) {
|
||||
gradientColor = lineGradient[0];
|
||||
} else {
|
||||
float clampedT = clamp(t, 0.0, 0.9999);
|
||||
float scaled = clampedT * float(lineGradientCount - 1);
|
||||
int idx = int(floor(scaled));
|
||||
float f = fract(scaled);
|
||||
int idx2 = min(idx + 1, lineGradientCount - 1);
|
||||
|
||||
vec3 c1 = lineGradient[idx];
|
||||
vec3 c2 = lineGradient[idx2];
|
||||
|
||||
gradientColor = mix(c1, c2, f);
|
||||
}
|
||||
|
||||
return gradientColor * 0.5;
|
||||
}
|
||||
|
||||
float wave(vec2 uv, float offset, vec2 screenUv, vec2 mouseUv, bool shouldBend) {
|
||||
float time = iTime * animationSpeed;
|
||||
|
||||
float x_offset = offset;
|
||||
float x_movement = time * 0.1;
|
||||
float amp = sin(offset + time * 0.2) * 0.3;
|
||||
float y = sin(uv.x + x_offset + x_movement) * amp;
|
||||
|
||||
if (shouldBend) {
|
||||
vec2 d = screenUv - mouseUv;
|
||||
float influence = exp(-dot(d, d) * bendRadius);
|
||||
float bendOffset = (mouseUv.y - screenUv.y) * influence * bendStrength * bendInfluence;
|
||||
y += bendOffset;
|
||||
}
|
||||
|
||||
float m = uv.y - y;
|
||||
return 0.0175 / max(abs(m) + 0.01, 1e-3) + 0.01;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 baseUv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;
|
||||
baseUv.y *= -1.0;
|
||||
|
||||
if (parallax) {
|
||||
baseUv += parallaxOffset;
|
||||
}
|
||||
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
vec3 b = lineGradientCount > 0 ? vec3(0.0) : background_color(baseUv);
|
||||
|
||||
vec2 mouseUv = vec2(0.0);
|
||||
if (interactive) {
|
||||
mouseUv = (2.0 * iMouse - iResolution.xy) / iResolution.y;
|
||||
mouseUv.y *= -1.0;
|
||||
}
|
||||
|
||||
if (enableBottom) {
|
||||
for (int i = 0; i < bottomLineCount; ++i) {
|
||||
float fi = float(i);
|
||||
float t = fi / max(float(bottomLineCount - 1), 1.0);
|
||||
vec3 lineCol = getLineColor(t, b);
|
||||
|
||||
float angle = bottomWavePosition.z * log(length(baseUv) + 1.0);
|
||||
vec2 ruv = baseUv * rotate(angle);
|
||||
col += lineCol * wave(
|
||||
ruv + vec2(bottomLineDistance * fi + bottomWavePosition.x, bottomWavePosition.y),
|
||||
1.5 + 0.2 * fi,
|
||||
baseUv,
|
||||
mouseUv,
|
||||
interactive
|
||||
) * 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
if (enableMiddle) {
|
||||
for (int i = 0; i < middleLineCount; ++i) {
|
||||
float fi = float(i);
|
||||
float t = fi / max(float(middleLineCount - 1), 1.0);
|
||||
vec3 lineCol = getLineColor(t, b);
|
||||
|
||||
float angle = middleWavePosition.z * log(length(baseUv) + 1.0);
|
||||
vec2 ruv = baseUv * rotate(angle);
|
||||
col += lineCol * wave(
|
||||
ruv + vec2(middleLineDistance * fi + middleWavePosition.x, middleWavePosition.y),
|
||||
2.0 + 0.15 * fi,
|
||||
baseUv,
|
||||
mouseUv,
|
||||
interactive
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (enableTop) {
|
||||
for (int i = 0; i < topLineCount; ++i) {
|
||||
float fi = float(i);
|
||||
float t = fi / max(float(topLineCount - 1), 1.0);
|
||||
vec3 lineCol = getLineColor(t, b);
|
||||
|
||||
float angle = topWavePosition.z * log(length(baseUv) + 1.0);
|
||||
vec2 ruv = baseUv * rotate(angle);
|
||||
ruv.x *= -1.0;
|
||||
col += lineCol * wave(
|
||||
ruv + vec2(topLineDistance * fi + topWavePosition.x, topWavePosition.y),
|
||||
1.0 + 0.2 * fi,
|
||||
baseUv,
|
||||
mouseUv,
|
||||
interactive
|
||||
) * 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 color = vec4(0.0);
|
||||
mainImage(color, gl_FragCoord.xy);
|
||||
gl_FragColor = color;
|
||||
}
|
||||
`;
|
||||
|
||||
const MAX_GRADIENT_STOPS = 8;
|
||||
|
||||
type WavePosition = {
|
||||
x: number;
|
||||
y: number;
|
||||
rotate: number;
|
||||
};
|
||||
|
||||
type FloatingLinesProps = {
|
||||
linesGradient?: string[];
|
||||
enabledWaves?: Array<'top' | 'middle' | 'bottom'>;
|
||||
lineCount?: number | number[];
|
||||
lineDistance?: number | number[];
|
||||
topWavePosition?: WavePosition;
|
||||
middleWavePosition?: WavePosition;
|
||||
bottomWavePosition?: WavePosition;
|
||||
animationSpeed?: number;
|
||||
interactive?: boolean;
|
||||
bendRadius?: number;
|
||||
bendStrength?: number;
|
||||
mouseDamping?: number;
|
||||
parallax?: boolean;
|
||||
parallaxStrength?: number;
|
||||
mixBlendMode?: CSSProperties['mixBlendMode'];
|
||||
};
|
||||
|
||||
const props = withDefaults(defineProps<FloatingLinesProps>(), {
|
||||
enabledWaves: () => ['top', 'middle', 'bottom'],
|
||||
lineCount: () => [6],
|
||||
lineDistance: () => [5],
|
||||
bottomWavePosition: () => ({ x: 2.0, y: -0.7, rotate: -1 }),
|
||||
animationSpeed: 1,
|
||||
interactive: true,
|
||||
bendRadius: 5.0,
|
||||
bendStrength: -0.5,
|
||||
mouseDamping: 0.05,
|
||||
parallax: true,
|
||||
parallaxStrength: 0.2,
|
||||
mixBlendMode: 'screen'
|
||||
});
|
||||
|
||||
function hexToVec3(hex: string): Vector3 {
|
||||
let value = hex.trim();
|
||||
|
||||
if (value.startsWith('#')) {
|
||||
value = value.slice(1);
|
||||
}
|
||||
|
||||
let r = 255;
|
||||
let g = 255;
|
||||
let b = 255;
|
||||
|
||||
if (value.length === 3) {
|
||||
r = parseInt(value[0] + value[0], 16);
|
||||
g = parseInt(value[1] + value[1], 16);
|
||||
b = parseInt(value[2] + value[2], 16);
|
||||
} else if (value.length === 6) {
|
||||
r = parseInt(value.slice(0, 2), 16);
|
||||
g = parseInt(value.slice(2, 4), 16);
|
||||
b = parseInt(value.slice(4, 6), 16);
|
||||
}
|
||||
|
||||
return new Vector3(r / 255, g / 255, b / 255);
|
||||
}
|
||||
|
||||
const containerRef = useTemplateRef('containerRef');
|
||||
const targetMouseRef = ref<Vector2>(new Vector2(-1000, -1000));
|
||||
const currentMouseRef = ref<Vector2>(new Vector2(-1000, -1000));
|
||||
const targetInfluenceRef = ref<number>(0);
|
||||
const currentInfluenceRef = ref<number>(0);
|
||||
const targetParallaxRef = ref<Vector2>(new Vector2(0, 0));
|
||||
const currentParallaxRef = ref<Vector2>(new Vector2(0, 0));
|
||||
|
||||
let cleanup: (() => void) | null = null;
|
||||
const setup = () => {
|
||||
if (!containerRef.value) return;
|
||||
|
||||
const getLineCount = (waveType: 'top' | 'middle' | 'bottom'): number => {
|
||||
if (typeof props.lineCount === 'number') return props.lineCount;
|
||||
if (!props.enabledWaves.includes(waveType)) return 0;
|
||||
const index = props.enabledWaves.indexOf(waveType);
|
||||
return props.lineCount[index] ?? 6;
|
||||
};
|
||||
|
||||
const getLineDistance = (waveType: 'top' | 'middle' | 'bottom'): number => {
|
||||
if (typeof props.lineDistance === 'number') return props.lineDistance;
|
||||
if (!props.enabledWaves.includes(waveType)) return 0.1;
|
||||
const index = props.enabledWaves.indexOf(waveType);
|
||||
return props.lineDistance[index] ?? 0.1;
|
||||
};
|
||||
|
||||
const topLineCount = props.enabledWaves.includes('top') ? getLineCount('top') : 0;
|
||||
const middleLineCount = props.enabledWaves.includes('middle') ? getLineCount('middle') : 0;
|
||||
const bottomLineCount = props.enabledWaves.includes('bottom') ? getLineCount('bottom') : 0;
|
||||
|
||||
const topLineDistance = props.enabledWaves.includes('top') ? getLineDistance('top') * 0.01 : 0.01;
|
||||
const middleLineDistance = props.enabledWaves.includes('middle') ? getLineDistance('middle') * 0.01 : 0.01;
|
||||
const bottomLineDistance = props.enabledWaves.includes('bottom') ? getLineDistance('bottom') * 0.01 : 0.01;
|
||||
|
||||
const scene = new Scene();
|
||||
|
||||
const camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
||||
camera.position.z = 1;
|
||||
|
||||
const renderer = new WebGLRenderer({ antialias: true, alpha: false });
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
|
||||
renderer.domElement.style.width = '100%';
|
||||
renderer.domElement.style.height = '100%';
|
||||
containerRef.value.appendChild(renderer.domElement);
|
||||
|
||||
const uniforms = {
|
||||
iTime: { value: 0 },
|
||||
iResolution: { value: new Vector3(1, 1, 1) },
|
||||
animationSpeed: { value: props.animationSpeed },
|
||||
|
||||
enableTop: { value: props.enabledWaves.includes('top') },
|
||||
enableMiddle: { value: props.enabledWaves.includes('middle') },
|
||||
enableBottom: { value: props.enabledWaves.includes('bottom') },
|
||||
|
||||
topLineCount: { value: topLineCount },
|
||||
middleLineCount: { value: middleLineCount },
|
||||
bottomLineCount: { value: bottomLineCount },
|
||||
|
||||
topLineDistance: { value: topLineDistance },
|
||||
middleLineDistance: { value: middleLineDistance },
|
||||
bottomLineDistance: { value: bottomLineDistance },
|
||||
|
||||
topWavePosition: {
|
||||
value: new Vector3(
|
||||
props.topWavePosition?.x ?? 10.0,
|
||||
props.topWavePosition?.y ?? 0.5,
|
||||
props.topWavePosition?.rotate ?? -0.4
|
||||
)
|
||||
},
|
||||
middleWavePosition: {
|
||||
value: new Vector3(
|
||||
props.middleWavePosition?.x ?? 5.0,
|
||||
props.middleWavePosition?.y ?? 0.0,
|
||||
props.middleWavePosition?.rotate ?? 0.2
|
||||
)
|
||||
},
|
||||
bottomWavePosition: {
|
||||
value: new Vector3(
|
||||
props.bottomWavePosition?.x ?? 2.0,
|
||||
props.bottomWavePosition?.y ?? -0.7,
|
||||
props.bottomWavePosition?.rotate ?? 0.4
|
||||
)
|
||||
},
|
||||
|
||||
iMouse: { value: new Vector2(-1000, -1000) },
|
||||
interactive: { value: props.interactive },
|
||||
bendRadius: { value: props.bendRadius },
|
||||
bendStrength: { value: props.bendStrength },
|
||||
bendInfluence: { value: 0 },
|
||||
|
||||
parallax: { value: props.parallax },
|
||||
parallaxStrength: { value: props.parallaxStrength },
|
||||
parallaxOffset: { value: new Vector2(0, 0) },
|
||||
|
||||
lineGradient: {
|
||||
value: Array.from({ length: MAX_GRADIENT_STOPS }, () => new Vector3(1, 1, 1))
|
||||
},
|
||||
lineGradientCount: { value: 0 }
|
||||
};
|
||||
|
||||
if (props.linesGradient && props.linesGradient.length > 0) {
|
||||
const stops = props.linesGradient.slice(0, MAX_GRADIENT_STOPS);
|
||||
uniforms.lineGradientCount.value = stops.length;
|
||||
|
||||
stops.forEach((hex, i) => {
|
||||
const color = hexToVec3(hex);
|
||||
uniforms.lineGradient.value[i].set(color.x, color.y, color.z);
|
||||
});
|
||||
}
|
||||
|
||||
const material = new ShaderMaterial({
|
||||
uniforms,
|
||||
vertexShader,
|
||||
fragmentShader
|
||||
});
|
||||
|
||||
const geometry = new PlaneGeometry(2, 2);
|
||||
const mesh = new Mesh(geometry, material);
|
||||
scene.add(mesh);
|
||||
|
||||
const clock = new Clock();
|
||||
|
||||
const setSize = () => {
|
||||
const el = containerRef.value!;
|
||||
const width = el.clientWidth || 1;
|
||||
const height = el.clientHeight || 1;
|
||||
|
||||
renderer.setSize(width, height, false);
|
||||
|
||||
const canvasWidth = renderer.domElement.width;
|
||||
const canvasHeight = renderer.domElement.height;
|
||||
uniforms.iResolution.value.set(canvasWidth, canvasHeight, 1);
|
||||
};
|
||||
|
||||
setSize();
|
||||
|
||||
const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(setSize) : null;
|
||||
|
||||
if (ro && containerRef.value) {
|
||||
ro.observe(containerRef.value);
|
||||
}
|
||||
|
||||
const handlePointerMove = (event: PointerEvent) => {
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
const x = event.clientX - rect.left;
|
||||
const y = event.clientY - rect.top;
|
||||
const dpr = renderer.getPixelRatio();
|
||||
|
||||
targetMouseRef.value.set(x * dpr, (rect.height - y) * dpr);
|
||||
targetInfluenceRef.value = 1.0;
|
||||
|
||||
if (props.parallax) {
|
||||
const centerX = rect.width / 2;
|
||||
const centerY = rect.height / 2;
|
||||
const offsetX = (x - centerX) / rect.width;
|
||||
const offsetY = -(y - centerY) / rect.height;
|
||||
targetParallaxRef.value.set(offsetX * props.parallaxStrength, offsetY * props.parallaxStrength);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePointerLeave = () => {
|
||||
targetInfluenceRef.value = 0.0;
|
||||
};
|
||||
|
||||
if (props.interactive) {
|
||||
renderer.domElement.addEventListener('pointermove', handlePointerMove);
|
||||
renderer.domElement.addEventListener('pointerleave', handlePointerLeave);
|
||||
}
|
||||
|
||||
let raf = 0;
|
||||
const renderLoop = () => {
|
||||
uniforms.iTime.value = clock.getElapsedTime();
|
||||
|
||||
if (props.interactive) {
|
||||
currentMouseRef.value.lerp(targetMouseRef.value, props.mouseDamping);
|
||||
uniforms.iMouse.value.copy(currentMouseRef.value);
|
||||
|
||||
currentInfluenceRef.value += (targetInfluenceRef.value - currentInfluenceRef.value) * props.mouseDamping;
|
||||
uniforms.bendInfluence.value = currentInfluenceRef.value;
|
||||
}
|
||||
|
||||
if (props.parallax) {
|
||||
currentParallaxRef.value.lerp(targetParallaxRef.value, props.mouseDamping);
|
||||
uniforms.parallaxOffset.value.copy(currentParallaxRef.value);
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
raf = requestAnimationFrame(renderLoop);
|
||||
};
|
||||
renderLoop();
|
||||
|
||||
cleanup = () => {
|
||||
cancelAnimationFrame(raf);
|
||||
if (ro && containerRef.value) {
|
||||
ro.disconnect();
|
||||
}
|
||||
|
||||
if (props.interactive) {
|
||||
renderer.domElement.removeEventListener('pointermove', handlePointerMove);
|
||||
renderer.domElement.removeEventListener('pointerleave', handlePointerLeave);
|
||||
}
|
||||
|
||||
geometry.dispose();
|
||||
material.dispose();
|
||||
renderer.dispose();
|
||||
if (renderer.domElement.parentElement) {
|
||||
renderer.domElement.parentElement.removeChild(renderer.domElement);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setup();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
cleanup?.();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [
|
||||
props.linesGradient,
|
||||
props.enabledWaves,
|
||||
props.lineCount,
|
||||
props.lineDistance,
|
||||
props.topWavePosition,
|
||||
props.middleWavePosition,
|
||||
props.bottomWavePosition,
|
||||
props.animationSpeed,
|
||||
props.interactive,
|
||||
props.bendRadius,
|
||||
props.bendStrength,
|
||||
props.mouseDamping,
|
||||
props.parallax,
|
||||
props.parallaxStrength
|
||||
],
|
||||
() => {
|
||||
cleanup?.();
|
||||
setup();
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="containerRef" class="relative w-full h-full overflow-hidden floating-lines-container" :style="{
|
||||
mixBlendMode: mixBlendMode
|
||||
}" />
|
||||
</template>
|
||||
@ -4,18 +4,10 @@
|
||||
<template v-if="values.includes(item.value)">
|
||||
<span
|
||||
v-if="(item.elTagType == 'default' || item.elTagType == '') && (item.elTagClass == '' || item.elTagClass == null)"
|
||||
:key="item.value"
|
||||
:index="index"
|
||||
:class="item.elTagClass"
|
||||
>{{ item.label + " " }}</span>
|
||||
<el-tag
|
||||
v-else
|
||||
:disable-transitions="true"
|
||||
:key="item.value + ''"
|
||||
:index="index"
|
||||
:type="item.elTagType === 'primary' ? '' : item.elTagType"
|
||||
:class="item.elTagClass"
|
||||
>{{ item.label + " " }}</el-tag>
|
||||
:key="item.value" :index="index" :class="item.elTagClass">{{ item.label + " " }}</span>
|
||||
<el-tag v-else :disable-transitions="true" :key="item.value + ''" :index="index"
|
||||
:type="item.elTagType === 'default' ? 'primary' : item.elTagType" :class="item.elTagClass">{{ item.label + " "
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="unmatch && showValue">
|
||||
@ -76,7 +68,7 @@ function handleArray(array) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-tag + .el-tag {
|
||||
.el-tag+.el-tag {
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
330
src/components/DoubleClickInputTable/index.vue
Normal file
@ -0,0 +1,330 @@
|
||||
<template>
|
||||
<div class="double-click-input-table" ref="componentRef">
|
||||
<!-- 输入框 -->
|
||||
<el-input ref="inputRef" v-model="inputValue" class="full-width-input" :placeholder="placeholder"
|
||||
:disabled="disabled" @dblclick="handleDoubleClick" @change="handleInputBlur" />
|
||||
|
||||
<!-- 下拉表格面板 -->
|
||||
<el-popover ref="popoverRef" v-model:visible="isPopoverVisible" :width="popoverWidth" trigger="click"
|
||||
placement="bottom-start" :teleported="false" @hide="handlePopoverHide">
|
||||
<!-- 搜索框 -->
|
||||
<el-input ref="searchInputRef" v-model="searchKeyword" placeholder="搜索..." size="small" class="search-input"
|
||||
@input="handleSearch" @keydown="handleSearchKeydown" />
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table ref="tableRef" :data="filteredData" :height="tableHeight" highlight-current-row
|
||||
:current-row-key="currentRowKey" @row-dblclick="handleRowDblClick" class="select-table">
|
||||
<!-- 动态渲染列 -->
|
||||
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.label"
|
||||
:width="column.width" :align="column.align || 'left'" />
|
||||
</el-table>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, nextTick, onMounted, defineProps, defineEmits, toRefs } from 'vue';
|
||||
import { ElInput, ElPopover, ElTable, ElTableColumn } from 'element-plus';
|
||||
|
||||
// 定义列的类型
|
||||
interface TableColumn {
|
||||
prop: string;
|
||||
label: string;
|
||||
width?: number | string;
|
||||
align?: 'left' | 'center' | 'right';
|
||||
}
|
||||
|
||||
interface DataItem {
|
||||
[key: string]: any; // 或者更严格的字段定义
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: string | number | DataItem;
|
||||
data: DataItem[];
|
||||
columns: TableColumn[];
|
||||
labelField: string;
|
||||
valueField: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
popoverWidth?: number | string;
|
||||
tableHeight?: number | string;
|
||||
searchable?: boolean;
|
||||
}>();
|
||||
|
||||
|
||||
|
||||
// 定义事件
|
||||
const emits = defineEmits(['update:modelValue', 'change', 'select', 'visible-change']);
|
||||
|
||||
// 解构 props
|
||||
const { modelValue, data, columns, labelField, valueField, searchable } = toRefs(props);
|
||||
|
||||
// 组件内部状态
|
||||
const inputValue = ref('');
|
||||
const isPopoverVisible = ref(false);
|
||||
const searchKeyword = ref('');
|
||||
const filteredData = ref<any[]>([]);
|
||||
const currentRowKey = ref('');
|
||||
const currentIndex = ref(-1);
|
||||
const isInputFocused = ref(false);
|
||||
|
||||
// 引用
|
||||
const inputRef = ref<InstanceType<typeof ElInput>>();
|
||||
const popoverRef = ref<InstanceType<typeof ElPopover>>();
|
||||
const tableRef = ref<InstanceType<typeof ElTable>>();
|
||||
const searchInputRef = ref<InstanceType<typeof ElInput>>();
|
||||
const componentRef = ref<HTMLElement | null>(null);
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
filteredData.value = [...data.value];
|
||||
syncInputValue();
|
||||
|
||||
// 监听数据变化
|
||||
watch(data, (newVal) => {
|
||||
filteredData.value = [...newVal];
|
||||
handleSearch();
|
||||
});
|
||||
|
||||
// 监听选中值变化
|
||||
watch(modelValue, () => {
|
||||
syncInputValue();
|
||||
});
|
||||
});
|
||||
|
||||
// 同步输入框值
|
||||
const syncInputValue = () => {
|
||||
if (modelValue.value && typeof modelValue.value === 'object') {
|
||||
inputValue.value = modelValue.value[labelField.value] || '';
|
||||
setCurrentRow(modelValue.value);
|
||||
} else if (modelValue.value) {
|
||||
// 当值不是对象时,查找对应的数据
|
||||
const found = data.value.find((item: any) => item[valueField.value] === modelValue.value);
|
||||
inputValue.value = found ? found[labelField.value] : '';
|
||||
setCurrentRow(found);
|
||||
} else {
|
||||
inputValue.value = '';
|
||||
currentRowKey.value = '';
|
||||
currentIndex.value = -1;
|
||||
}
|
||||
};
|
||||
|
||||
// 设置当前选中行
|
||||
const setCurrentRow = (row: any) => {
|
||||
if (!row) return;
|
||||
|
||||
currentRowKey.value = row[valueField.value];
|
||||
const index = filteredData.value.findIndex(item => item[valueField.value] === row[valueField.value]);
|
||||
if (index !== -1) {
|
||||
currentIndex.value = index;
|
||||
}
|
||||
};
|
||||
|
||||
// 双击输入框显示下拉面板
|
||||
const handleDoubleClick = () => {
|
||||
if (props.disabled) return;
|
||||
|
||||
isPopoverVisible.value = true;
|
||||
emits('visible-change', true);
|
||||
|
||||
// 延迟聚焦搜索框,确保弹窗已渲染
|
||||
nextTick(() => {
|
||||
if (searchable.value && searchInputRef.value) {
|
||||
searchInputRef.value.focus();
|
||||
} else if (tableRef.value) {
|
||||
// 如果不可搜索,聚焦表格
|
||||
const tableEl = tableRef.value.$el.querySelector('.el-table__body-wrapper');
|
||||
tableEl?.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理搜索
|
||||
const handleSearch = () => {
|
||||
const keyword = searchKeyword.value.toLowerCase().trim();
|
||||
|
||||
if (!keyword) {
|
||||
filteredData.value = [...data.value];
|
||||
currentIndex.value = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// 过滤数据,在所有列中搜索
|
||||
filteredData.value = data.value.filter((item: any) => {
|
||||
return columns.value.some(column => {
|
||||
const value = item[column.prop];
|
||||
return value !== null && value !== undefined &&
|
||||
String(value).toLowerCase().includes(keyword);
|
||||
});
|
||||
});
|
||||
|
||||
// 重置当前索引
|
||||
currentIndex.value = filteredData.value.length > 0 ? 0 : -1;
|
||||
if (currentIndex.value !== -1) {
|
||||
currentRowKey.value = filteredData.value[0][valueField.value];
|
||||
scrollToCurrentRow();
|
||||
} else {
|
||||
currentRowKey.value = '';
|
||||
}
|
||||
};
|
||||
|
||||
// 表格行点击
|
||||
const handleRowClick = (row: any) => {
|
||||
currentRowKey.value = row[valueField.value];
|
||||
currentIndex.value = filteredData.value.findIndex(item => item[valueField.value] === row[valueField.value]);
|
||||
};
|
||||
|
||||
// 表格行双击
|
||||
const handleRowDblClick = (row: any) => {
|
||||
selectRow(row);
|
||||
};
|
||||
|
||||
// 选择行
|
||||
const selectRow = (row: any) => {
|
||||
if (!row) return;
|
||||
|
||||
inputValue.value = row[labelField.value];
|
||||
emits('update:modelValue', row[valueField.value]);
|
||||
emits('change', row[valueField.value]);
|
||||
emits('select', row);
|
||||
|
||||
isPopoverVisible.value = false;
|
||||
emits('visible-change',);
|
||||
|
||||
// 聚焦输入框
|
||||
nextTick(() => {
|
||||
inputRef.value?.focus();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 处理输入框失焦
|
||||
const handleInputBlur = () => {
|
||||
emits('visible-change');
|
||||
};
|
||||
|
||||
// 处理输入框键盘事件
|
||||
const handleInputKeydown = (e: any) => {
|
||||
// 按向下箭头显示下拉面板
|
||||
if (e.key === 'ArrowDown' && isInputFocused.value) {
|
||||
e.preventDefault();
|
||||
handleDoubleClick();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理搜索框键盘事件
|
||||
const handleSearchKeydown = (e: any) => {
|
||||
// 上下箭头控制表格选择
|
||||
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
handleArrowKey(e.key);
|
||||
}
|
||||
// 回车键选择
|
||||
else if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if (currentIndex.value !== -1 && filteredData.value[currentIndex.value]) {
|
||||
selectRow(filteredData.value[currentIndex.value]);
|
||||
}
|
||||
}
|
||||
// ESC键关闭
|
||||
else if (e.key === 'Escape') {
|
||||
isPopoverVisible.value = false;
|
||||
emits('visible-change', false);
|
||||
inputRef.value?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
// 处理箭头键
|
||||
const handleArrowKey = (direction: 'ArrowUp' | 'ArrowDown') => {
|
||||
if (filteredData.value.length === 0) return;
|
||||
|
||||
if (direction === 'ArrowUp') {
|
||||
currentIndex.value = Math.max(0, currentIndex.value - 1);
|
||||
} else {
|
||||
currentIndex.value = Math.min(filteredData.value.length - 1, currentIndex.value + 1);
|
||||
}
|
||||
|
||||
const currentRow = filteredData.value[currentIndex.value];
|
||||
currentRowKey.value = currentRow[valueField.value];
|
||||
scrollToCurrentRow();
|
||||
};
|
||||
|
||||
// 滚动到当前行
|
||||
const scrollToCurrentRow = () => {
|
||||
nextTick(() => {
|
||||
const table = tableRef.value;
|
||||
if (!table) return;
|
||||
|
||||
const rowEl = table.$el.querySelector(`.el-table__row[current-row-key="${currentRowKey.value}"]`);
|
||||
const scrollContainer = table.$el.querySelector('.el-table__body-wrapper');
|
||||
|
||||
if (rowEl && scrollContainer) {
|
||||
// 计算滚动位置,使当前行居中
|
||||
const containerHeight = scrollContainer.clientHeight;
|
||||
const rowHeight = rowEl.offsetHeight;
|
||||
const rowTop = rowEl.offsetTop;
|
||||
const scrollTop = rowTop - containerHeight / 2 + rowHeight / 2;
|
||||
|
||||
scrollContainer.scrollTo({
|
||||
top: scrollTop,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理弹窗隐藏
|
||||
const handlePopoverHide = () => {
|
||||
searchKeyword.value = '';
|
||||
handleSearch(); // 重置搜索
|
||||
emits('visible-change', false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.full-width-input .el-input__inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.full-width-input {
|
||||
:deep(.el-input__wrapper) {
|
||||
// box-shadow: 0 0 0 1px rgba(64, 158, 255, 0.2);
|
||||
box-shadow: none;
|
||||
background: transparent !important;
|
||||
padding: 0 !important;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.double-click-input-table {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .el-table__body-wrapper {
|
||||
tabindex: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
::v-deep .el-table__row.current-row {
|
||||
background-color: #e6f7ff !important;
|
||||
}
|
||||
</style>
|
||||
109
src/components/PrintReportMask/index.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div v-if="visible" class="print-mask">
|
||||
<div class="mask-card">
|
||||
<div class="card-header">
|
||||
<div class="title">打印报告进度</div>
|
||||
<el-button icon="Close" circle size="small" v-if="progress == 100" @click="closeMask" />
|
||||
</div>
|
||||
<div class="tip-text">{{ ybh }} {{ desc }}</div>
|
||||
<el-progress :percentage="progress" :stroke-width="15" striped />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { classCom } from '@/utils/classCom';
|
||||
const props = defineProps<{
|
||||
// websocket原始data字符串
|
||||
wsData?: string
|
||||
}>()
|
||||
const visible = ref(false)
|
||||
const ybh = ref('')
|
||||
const desc = ref('')
|
||||
const progress = ref(0)
|
||||
const succCount = ref(0)
|
||||
const failCount = ref(0)
|
||||
const errorMsg = ref('')
|
||||
// 解析ws数据
|
||||
const parseWsData = (dataStr: string) => {
|
||||
try {
|
||||
const data = JSON.parse(dataStr)
|
||||
ybh.value = data.ybh
|
||||
desc.value = data.desc
|
||||
progress.value = data.progress
|
||||
succCount.value = data.succCount
|
||||
failCount.value = data.failCount
|
||||
errorMsg.value = data.errorMsg
|
||||
visible.value = true
|
||||
// 100%完成后打印PDF
|
||||
if (data.progress == 100) {
|
||||
classCom.printBase64PDF(data.pdfBase64)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('打印ws数据解析失败', err)
|
||||
}
|
||||
}
|
||||
watch(
|
||||
() => props.wsData,
|
||||
(val) => {
|
||||
if (val) parseWsData(val)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
// 对外暴露手动关闭方法
|
||||
const closeMask = () => {
|
||||
visible.value = false
|
||||
}
|
||||
defineExpose({ closeMask })
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.print-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
|
||||
.mask-card {
|
||||
background: #fff;
|
||||
width: 460px;
|
||||
padding: 24px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
|
||||
|
||||
// 标题行布局
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16;
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1d2129;
|
||||
}
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #4e5969;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.7;
|
||||
font-size: 14px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.finish-text {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
color: #00b42a;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -8,14 +8,16 @@
|
||||
<el-button circle icon="Refresh" @click="refresh()" />
|
||||
</el-tooltip>
|
||||
<el-tooltip class="item" effect="dark" content="显隐列" placement="top" v-if="columns">
|
||||
<el-button circle icon="Menu" @click="showColumn()" v-if="showColumnsType == 'transfer'"/>
|
||||
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px" v-if="showColumnsType == 'checkbox'">
|
||||
<el-button circle icon="Menu" @click="showColumn()" v-if="showColumnsType == 'transfer'" />
|
||||
<el-dropdown trigger="click" :hide-on-click="false" style="padding-left: 12px"
|
||||
v-if="showColumnsType == 'checkbox'">
|
||||
<el-button circle icon="Menu" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<template v-for="item in columns" :key="item.key">
|
||||
<el-dropdown-item>
|
||||
<el-checkbox :checked="item.visible" @change="checkboxChange($event, item.label)" :label="item.label" />
|
||||
<el-checkbox :checked="item.visible" @change="checkboxChange($event, item.label)"
|
||||
:label="item.label" />
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
</el-dropdown-menu>
|
||||
@ -24,12 +26,7 @@
|
||||
</el-tooltip>
|
||||
</el-row>
|
||||
<el-dialog :title="title" v-model="open" append-to-body>
|
||||
<el-transfer
|
||||
:titles="['显示', '隐藏']"
|
||||
v-model="value"
|
||||
:data="columns"
|
||||
@change="dataChange"
|
||||
></el-transfer>
|
||||
<el-transfer :titles="['显示', '隐藏']" v-model="value" :data="columns" @change="dataChange"></el-transfer>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@ -62,7 +59,7 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits(['update:showSearch', 'queryTable']);
|
||||
const emits = defineEmits(['update:showSearch', 'queryTable', 'updateColumns']);
|
||||
|
||||
// 显隐数据
|
||||
const value = ref([]);
|
||||
@ -114,6 +111,9 @@ if (props.showColumnsType == 'transfer') {
|
||||
// 勾选
|
||||
function checkboxChange(event, label) {
|
||||
props.columns.filter(item => item.label == label)[0].visible = event;
|
||||
|
||||
emits("updateColumns", toRaw(props.columns));
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -124,9 +124,11 @@ function checkboxChange(event, label) {
|
||||
display: block;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
:deep(.el-transfer__button:first-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-dropdown-menu__item) {
|
||||
line-height: 30px;
|
||||
padding: 0 17px;
|
||||
|
||||
77
src/components/SelectTable/YQSelectTable/index.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<!--仪器组件的封装-->
|
||||
<template>
|
||||
<SelectTable v-model:data="modelValue" :fields="fields" :tableData="instrOptions" label="yqmc" :size="props.size"
|
||||
value="yq" objKey="yq" :border="true" :width="props.width" placeholder="请选择仪器" :clearable="props.clearable"
|
||||
@getDataValue="getDataValue" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import SelectTable from '@/components/SelectTable/index.vue';
|
||||
import { getGroupInstrdList } from '@/api/liswork/work/LisWork';
|
||||
import { Emits, Props, Field } from '@/types';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
|
||||
|
||||
const modelValue = ref<string | null>('');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
width?: string | number,
|
||||
size?: string,
|
||||
clearable?: boolean,
|
||||
instrGroup?: string | number, //部门组代号
|
||||
data: string | undefined
|
||||
}>(), {
|
||||
width: '100%',
|
||||
size: 'default',
|
||||
clearable: false,
|
||||
data: ''
|
||||
})
|
||||
|
||||
const instrOptions = ref<Array<{ yq: string; yqmc: string; yqdl: string }>>([]);
|
||||
|
||||
const fields = ref(
|
||||
[
|
||||
{ prop: 'yq', label: '代号', width: 80, enablePinyinSearch: true },
|
||||
{ prop: 'yqmc', label: '名称', enablePinyinSearch: true },
|
||||
]
|
||||
)
|
||||
const emits = defineEmits<Emits>();
|
||||
|
||||
|
||||
const getYqConfig = () => {
|
||||
const data = {
|
||||
lisgroup: props.instrGroup
|
||||
}
|
||||
getGroupInstrdList(data)
|
||||
.then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
instrOptions.value = res.data.map((item: any) => ({
|
||||
yq: item.yq.trim(),
|
||||
yqmc: item.yqmc,
|
||||
yqdl: item.yqdl,
|
||||
lisgroupid: item.lisgroup
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getDataValue = (val: any) => {
|
||||
emits('update:data', val?.yq || null);
|
||||
emits('getDataValue', val || null);
|
||||
};
|
||||
|
||||
watch(() => props.data, (val) => {
|
||||
modelValue.value = val;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
// 初始化时同步一次父级值(如果有)到内部 modelValue
|
||||
if (props.data !== undefined && props.data !== null) {
|
||||
modelValue.value = props.data as any;
|
||||
}
|
||||
getYqConfig();
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
407
src/components/SelectTable/index.vue
Normal file
@ -0,0 +1,407 @@
|
||||
<!--
|
||||
* SelectTable 下拉表格组件
|
||||
* @author: w
|
||||
* @since: 2025-9-28
|
||||
* SelectTable.vue
|
||||
*
|
||||
* 属性(带有[Required]为必填属性)
|
||||
* data[Required]: 双向绑定数据
|
||||
* fields[Required]: 表格列对象
|
||||
* tableData[Required]: 表格数据对象
|
||||
* value: 双向绑定数据的值(为空时data属性为表格当前行数据对象)
|
||||
* label: 选择框显示的文本内容(为空时分别查看value和objKey是否为空,若value和objKey都有值,则value优先级大于objKey)
|
||||
* objKey: 对象key(绑定值的唯一标识,绑定值为对象时必填) 数据回显对应值
|
||||
* placeholder: 选择框占位文本
|
||||
* size: 组件大小
|
||||
* border: 表格是否带有边框
|
||||
-->
|
||||
<template>
|
||||
<div class="select-table-container">
|
||||
<el-select ref="selectTable" class="select-table__wrapper" v-model="selectShowValue"
|
||||
:placeholder="props.placeholder" :size="props.size" :style="{ width: props.width }"
|
||||
@visible-change="visibleChange" @clear="clearHandle" :clearable="props.clearable" :disabled="disabled"
|
||||
v-bind="$attrs">
|
||||
<template #empty>
|
||||
<div class="select-table-dropdown">
|
||||
<div style="text-align: left;">
|
||||
<el-input v-model="searchKey" ref="searchInput" size="small" placeholder="快速搜索(支持简拼)" class="mb10" clearable
|
||||
@clear="filterDataHandle" @input="filterDataHandle" @keydown="handleInputKeydown" />
|
||||
</div>
|
||||
<!-- 数据为空时显示空状态提示 -->
|
||||
<el-empty v-if="filterData.length === 0" description="没有匹配的数据" :image-size="100" />
|
||||
<div @keydown="handleKeydown" v-else tabindex="0" style="outline: none;">
|
||||
<!-- 数据存在时显示表格 -->
|
||||
<!-- <el-table ref="tableRef" :data="filterData" :highlight-current-row="props.isHighlight" style="width: 100%"
|
||||
:border="props.border" @row-click="handleRowChange" max-height="350px" :row-style="{ height: '25px' }">
|
||||
<el-table-column v-for="field in props.fields" :prop="field.prop" :label="field.label"
|
||||
:width="field.width" show-overflow-tooltip align="center" />
|
||||
</el-table> -->
|
||||
<vxe-table class="mytable-style" ref="tableRef" border resizable max-height="350px"
|
||||
:row-config="{ isHover: true, keyField: 'value', height: 30, isCurrent: true }" :data="filterData"
|
||||
:current-row="currentRow" @cell-click="currentChange"
|
||||
:tooltip-config="{ appendToBody: true, zIndex: 3000 }" :show-overflow="true"
|
||||
:scroll-y="{ enabled: true, rSize: 30, height: '100%', oSize: 20, gt: 30, }">
|
||||
<vxe-table-column v-for="field in props.fields" :field="field.prop" :title="field.label" align="center"
|
||||
:width="field.width" min-width="150" />
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, onMounted, watch, nextTick, toRaw } from "vue";
|
||||
import { getFirstLetter } from '@/utils/pinyin';
|
||||
import { ElEmpty } from 'element-plus';
|
||||
import { comDict } from '@/utils/dict'
|
||||
import { getoptionselect } from '@/api/liswork/xtwh/localconfigApi'
|
||||
import { Emits, Props } from '@/types';
|
||||
import { getOptionSelect } from '@/hooks'
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
placeholder: "请选择",
|
||||
size: "default",
|
||||
isHighlight: true,
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
border: true,
|
||||
width: "100%",
|
||||
dictType: '',
|
||||
optionselect: false,
|
||||
clearable: true,
|
||||
objKey: 'value',
|
||||
keyValue: false,
|
||||
fields: () => [
|
||||
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
|
||||
{ prop: 'label', label: '名称', enablePinyinSearch: true },
|
||||
],
|
||||
});
|
||||
|
||||
const emits = defineEmits<Emits>();
|
||||
const searchKey = ref('');
|
||||
const tableRef = ref();
|
||||
const selectTable = ref();
|
||||
const selectShowValue = ref('');
|
||||
const searchInput = ref();
|
||||
const filterData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||
// 存储预处理后的带拼音数据
|
||||
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||
const currentIndex = ref(-1);
|
||||
const currentRow = ref<any>(null)
|
||||
// 字典数据存储
|
||||
const dictData = ref<Record<string, any[]>>({});
|
||||
// 预处理数据:生成拼音信息
|
||||
const processTableData = (data: object[]) => {
|
||||
return data.map((item: any) => {
|
||||
const pinyinMap: Record<string, string> = {};
|
||||
// 处理label字段拼音
|
||||
if (item[props.label!]) {
|
||||
pinyinMap.label = getFirstLetter(item[props.label!]).toLowerCase();
|
||||
}
|
||||
// 处理value字段拼音
|
||||
if (props.value && item[props.value]) {
|
||||
pinyinMap.value = getFirstLetter(String(item[props.value])).toLowerCase();
|
||||
}
|
||||
// 处理其他指定字段拼音
|
||||
props.fields.forEach(field => {
|
||||
if (field.enablePinyinSearch && item[field.prop]) {
|
||||
pinyinMap[field.prop] = getFirstLetter(item[field.prop]).toLowerCase();
|
||||
}
|
||||
});
|
||||
return { ...item, pinyinMap };
|
||||
});
|
||||
};
|
||||
|
||||
// 隐藏显示处理
|
||||
const visibleChange = (val: any) => {
|
||||
searchKey.value = '';
|
||||
if (val) {
|
||||
filterDataHandle()
|
||||
setTimeout(() => {
|
||||
searchInput.value.focus();
|
||||
|
||||
currentIndex.value = filterData.value.findIndex(item => item[props.value!] === props.data);
|
||||
if (currentIndex.value >= 0) {
|
||||
tableRef.value.setCurrentRow(filterData.value[currentIndex.value])
|
||||
tableRef.value.scrollToRow(filterData.value[currentIndex.value])
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 数据回显处理
|
||||
const handleDataEcho = () => {
|
||||
if (props.data === null || props.data === undefined) {
|
||||
selectShowValue.value = '';
|
||||
emits('update:data', null);
|
||||
// emits('getDataValue', null);
|
||||
|
||||
} else {
|
||||
// 查找匹配的行数据
|
||||
let row: any = []
|
||||
if (props.dictType) {
|
||||
row = dictData.value[props.dictType]?.find((item: any) => props.objKey && item[props.objKey] === props.data)
|
||||
} else if (props.tableData) {
|
||||
row = props.tableData?.find((item: any) => props.objKey && item[props.objKey] === props.data)
|
||||
}
|
||||
selectShowValue.value = row ? (props.keyValue ? `${row[props.value]} ${row[props.label]}` : (props.label ? row[props.label] : (props.value ? row[props.value] : ''))) : props.data;
|
||||
}
|
||||
};
|
||||
|
||||
interface DictRefs {
|
||||
[key: string]: {
|
||||
value: any[];
|
||||
};
|
||||
}
|
||||
// 初始化数据
|
||||
const initData = async () => {
|
||||
if (props.tableData) {
|
||||
// 如果传入tableData,直接使用
|
||||
processedTableData.value = processTableData(props.tableData);
|
||||
filterData.value = [...processedTableData.value];
|
||||
} else if (props.dictType) {
|
||||
|
||||
let dictRefs: DictRefs = {};
|
||||
// 如果传入dictType,通过comDict获取数据 optionselect为true 用通用接口
|
||||
if (props.optionselect) {
|
||||
const resp = await getoptionselect({ zdlb: props.dictType });
|
||||
const dictList = resp.data.map((p: any) => ({
|
||||
label: p.zdmc,
|
||||
value: p.zddh,
|
||||
}));
|
||||
|
||||
dictRefs[props.dictType] = { value: dictList };
|
||||
|
||||
getOptionSelect(props.dictType, dictList);
|
||||
} else {
|
||||
dictRefs = await comDict(props.dictType);
|
||||
}
|
||||
// // 从 ref 中获取实际数据
|
||||
dictData.value = {
|
||||
[props.dictType]: toRaw(dictRefs[props.dictType].value) || [],
|
||||
};
|
||||
processedTableData.value = processTableData(dictData.value[props.dictType]);
|
||||
filterData.value = [...processedTableData.value];
|
||||
}
|
||||
// 处理数据回显
|
||||
handleDataEcho();
|
||||
};
|
||||
|
||||
initData();
|
||||
// 初始化数据
|
||||
onMounted(() => {
|
||||
});
|
||||
|
||||
// 监听表格数据和字典类型变化
|
||||
watch(() => props.tableData, (newVal) => {
|
||||
if (newVal) {
|
||||
processedTableData.value = processTableData(newVal);
|
||||
handleDataEcho();
|
||||
}
|
||||
}, { deep: true });
|
||||
|
||||
// 监听绑定值数据变化,重新处理
|
||||
watch(() => props.data, (newVal) => {
|
||||
// 数据回显
|
||||
handleDataEcho();
|
||||
}, { deep: true });
|
||||
|
||||
|
||||
|
||||
// 输入框键盘事件处理(专门处理上下键)
|
||||
const handleInputKeydown = (e: KeyboardEvent) => {
|
||||
|
||||
// 仅处理上下方向回车键
|
||||
if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) return;
|
||||
// 阻止事件冒泡到输入框父元素
|
||||
e.stopPropagation();
|
||||
|
||||
// 如果有筛选数据,转移焦点到表格容器
|
||||
if (filterData.value.length > 0) {
|
||||
// 筛选后让表格容器获得焦点
|
||||
nextTick(() => {
|
||||
// 通过组件内部的 DOM 结构关系查找当前实例的表格容器 避免找不到table焦点
|
||||
const dropdown = searchInput.value.$el.closest('.select-table-dropdown');
|
||||
const tableContainer = dropdown?.querySelector('div[tabindex="0"]') as HTMLElement;
|
||||
if (tableContainer) {
|
||||
tableContainer.focus();
|
||||
}
|
||||
|
||||
// 手动触发一次表格容器的键盘事件
|
||||
const event = new KeyboardEvent('keydown', { key: e.key });
|
||||
tableContainer?.dispatchEvent(event);
|
||||
});
|
||||
|
||||
// 回车确认
|
||||
if (e.key === "Enter") {
|
||||
const currentRow = filterData.value[currentIndex.value];
|
||||
handleRowChange(currentRow);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 监听table键盘事件(核心)
|
||||
const handleKeydown = (e: any) => {
|
||||
// console.log('e==>', e);
|
||||
// 仅处理方向键和回车键
|
||||
if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) return;
|
||||
// 阻止默认行为(如页面滚动)
|
||||
e.preventDefault();
|
||||
|
||||
// 根据方向键更新“当前选中行索引”
|
||||
const maxIndex = filterData.value.length - 1; // 末行索引
|
||||
if (e.key === "ArrowUp") {
|
||||
// 按↑:索引减1,最小为0(首行)
|
||||
currentIndex.value = Math.max(0, currentIndex.value - 1);
|
||||
} else if (e.key === "ArrowDown") {
|
||||
// 按↓:索引加1,最大为 maxIndex(末行)
|
||||
currentIndex.value = Math.min(maxIndex, currentIndex.value + 1);
|
||||
}
|
||||
|
||||
tableRef.value.setCurrentRow(filterData.value[currentIndex.value])
|
||||
tableRef.value.scrollToRow(filterData.value[currentIndex.value])
|
||||
// 回车确认
|
||||
if (e.key === "Enter") {
|
||||
if (searchKey.value.trim() !== '') {
|
||||
// 如果输入框有内容,回车时先触发一次输入框的筛选逻辑,确保数据是最新的
|
||||
filterDataHandle();
|
||||
return
|
||||
}
|
||||
const currentRow = filterData.value[currentIndex.value];
|
||||
handleRowChange(currentRow);
|
||||
emits('enter-press');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 搜索过滤逻辑
|
||||
const filterDataHandle = () => {
|
||||
const key = searchKey.value.trim().toLowerCase();
|
||||
|
||||
if (!key) {
|
||||
// 空搜索时显示全部预处理数据
|
||||
filterData.value = [...processedTableData.value];
|
||||
return;
|
||||
} else {
|
||||
currentIndex.value = 0
|
||||
}
|
||||
|
||||
filterData.value = processedTableData.value.filter((item: any) => {
|
||||
// 1. 原文本匹配
|
||||
const matchLabel = props.label && item[props.label]?.toString().toLowerCase().includes(key);
|
||||
const matchValue = props.value && item[props.value]?.toString().toLowerCase().includes(key);
|
||||
|
||||
// 2. 拼音匹配
|
||||
const matchLabelPinyin = props.label && item.pinyinMap.label?.includes(key);
|
||||
const matchValuePinyin = props.value && item.pinyinMap.value?.includes(key);
|
||||
|
||||
// 3. 其他字段匹配
|
||||
let matchOtherField = false;
|
||||
props.fields.forEach(field => {
|
||||
if (field.enablePinyinSearch) {
|
||||
const textMatch = item[field.prop]?.toString().toLowerCase().includes(key);
|
||||
const pinyinMatch = item.pinyinMap[field.prop]?.includes(key);
|
||||
if (textMatch || pinyinMatch) {
|
||||
matchOtherField = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return matchLabel || matchValue || matchLabelPinyin || matchValuePinyin || matchOtherField;
|
||||
});
|
||||
|
||||
if (filterData.value.length > 0) {
|
||||
nextTick(() => {
|
||||
tableRef.value.setCurrentRow(filterData.value[0])
|
||||
tableRef.value.scrollToRow(filterData.value[0])
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const currentChange = (params: { row: any }) => {
|
||||
currentRow.value = params.row
|
||||
handleRowChange(params.row)
|
||||
}
|
||||
|
||||
const handleRowChange = (val: any) => {
|
||||
emits("update:data", props.value ? val[props.value] : val);
|
||||
setLabel(val);
|
||||
};
|
||||
|
||||
const setLabel = (val: any) => {
|
||||
if (props.label) {
|
||||
selectShowValue.value = val[props.label];
|
||||
} else if (props.value) {
|
||||
selectShowValue.value = val[props.value];
|
||||
} else if (props.keyValue) {
|
||||
selectShowValue.value = `${val[props.value]} ${val[props.label]}`;
|
||||
}
|
||||
if (props.objKey) {
|
||||
// 返回值objKey对应的对象数据
|
||||
emits('getDataValue', val);
|
||||
}
|
||||
selectTable.value.blur();
|
||||
};
|
||||
// 清空值
|
||||
const clearHandle = () => {
|
||||
selectShowValue.value = '';
|
||||
currentRow.value = null;
|
||||
emits("update:data", null);
|
||||
emits('getDataValue', null);
|
||||
tableRef.value?.clearCurrentRow();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.select-table-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.vxe-header--row th) {
|
||||
border-color: #1F6DD3;
|
||||
background-color: #1F6DD3;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.vxe-body--row td) {
|
||||
border-color: #1F6DD3;
|
||||
}
|
||||
|
||||
:deep(.vxe-table--row-hover) {
|
||||
background-color: #1F6DD3;
|
||||
}
|
||||
|
||||
:deep(.vxe-table--current-row) {
|
||||
background-color: #1F6DD3;
|
||||
}
|
||||
|
||||
:deep(.el-table-header-cell) {
|
||||
cursor: move;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
// 表格边框
|
||||
:deep(.vxe-table--render-default.border--full .vxe-body--column) {
|
||||
background-image: linear-gradient(#96B8D9, #96B8D9), linear-gradient(#96B8D9, #96B8D9) !important;
|
||||
}
|
||||
|
||||
// 表头边框
|
||||
:deep(.vxe-table--render-default.border--full .vxe-header--column) {
|
||||
background-image: linear-gradient(#1F6DD3, #1F6DD3), linear-gradient(#1F6DD3, #1F6DD3) !important;
|
||||
}
|
||||
|
||||
.select-table-dropdown {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
:deep(.el-table .el-table__cell) {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@ -1,31 +1,19 @@
|
||||
<template>
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
mode="horizontal"
|
||||
@select="handleSelect"
|
||||
:ellipsis="false"
|
||||
>
|
||||
<el-menu :default-active="activeMenu" mode="horizontal" @select="handleSelect" :ellipsis="false">
|
||||
<template v-for="(item, index) in topMenus">
|
||||
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber">
|
||||
<svg-icon
|
||||
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
|
||||
:icon-class="item.meta.icon"/>
|
||||
<el-menu-item :style="{ '--theme': theme }" :index="item.path" :key="index" v-if="index < visibleNumber">
|
||||
<svg-icon v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" :icon-class="item.meta.icon" />
|
||||
{{ item.meta.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<!-- 顶部菜单超出数量折叠 -->
|
||||
<el-sub-menu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber">
|
||||
<el-sub-menu :style="{ '--theme': theme }" index="more" v-if="topMenus.length > visibleNumber">
|
||||
<template #title>更多菜单</template>
|
||||
<template v-for="(item, index) in topMenus">
|
||||
<el-menu-item
|
||||
:index="item.path"
|
||||
:key="index"
|
||||
v-if="index >= visibleNumber">
|
||||
<svg-icon
|
||||
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
|
||||
:icon-class="item.meta.icon"/>
|
||||
{{ item.meta.title }}
|
||||
<el-menu-item :index="item.path" :key="index" v-if="index >= visibleNumber">
|
||||
<svg-icon v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" :icon-class="item.meta.icon" />
|
||||
{{ item.meta.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-sub-menu>
|
||||
@ -64,9 +52,9 @@ const topMenus = computed(() => {
|
||||
if (menu.hidden !== true) {
|
||||
// 兼容顶部栏一级菜单内部跳转
|
||||
if (menu.path === "/") {
|
||||
topMenus.push(menu.children[0]);
|
||||
topMenus.push(menu.children[0]);
|
||||
} else {
|
||||
topMenus.push(menu);
|
||||
topMenus.push(menu);
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -79,10 +67,10 @@ const childrenMenus = computed(() => {
|
||||
routers.value.map((router) => {
|
||||
for (let item in router.children) {
|
||||
if (router.children[item].parentPath === undefined) {
|
||||
if(router.path === "/") {
|
||||
if (router.path === "/") {
|
||||
router.children[item].path = "/" + router.children[item].path;
|
||||
} else {
|
||||
if(!isHttp(router.children[item].path)) {
|
||||
if (!isHttp(router.children[item].path)) {
|
||||
router.children[item].path = router.path + "/" + router.children[item].path;
|
||||
}
|
||||
}
|
||||
@ -102,9 +90,9 @@ const activeMenu = computed(() => {
|
||||
const tmpPath = path.substring(1, path.length);
|
||||
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
|
||||
if (!route.meta.link) {
|
||||
appStore.toggleSideBarHide(false);
|
||||
appStore.toggleSideBarHide(false);
|
||||
}
|
||||
} else if(!route.children) {
|
||||
} else if (!route.children) {
|
||||
activePath = path;
|
||||
appStore.toggleSideBarHide(true);
|
||||
}
|
||||
@ -149,7 +137,7 @@ function activeRoutes(key) {
|
||||
}
|
||||
});
|
||||
}
|
||||
if(routes.length > 0) {
|
||||
if (routes.length > 0) {
|
||||
permissionStore.setSidebarRouters(routes);
|
||||
} else {
|
||||
appStore.toggleSideBarHide(true);
|
||||
@ -170,7 +158,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.topmenu-container.el-menu--horizontal > .el-menu-item {
|
||||
.topmenu-container.el-menu--horizontal>.el-menu-item {
|
||||
float: left;
|
||||
height: 50px !important;
|
||||
line-height: 50px !important;
|
||||
@ -179,13 +167,14 @@ onMounted(() => {
|
||||
margin: 0 10px !important;
|
||||
}
|
||||
|
||||
.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-sub-menu.is-active .el-submenu__title {
|
||||
.topmenu-container.el-menu--horizontal>.el-menu-item.is-active,
|
||||
.el-menu--horizontal>.el-sub-menu.is-active .el-submenu__title {
|
||||
border-bottom: 2px solid #{'var(--theme)'} !important;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* sub-menu item */
|
||||
.topmenu-container.el-menu--horizontal > .el-sub-menu .el-sub-menu__title {
|
||||
.topmenu-container.el-menu--horizontal>.el-sub-menu .el-sub-menu__title {
|
||||
float: left;
|
||||
height: 50px !important;
|
||||
line-height: 50px !important;
|
||||
@ -195,7 +184,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
/* 背景色隐藏 */
|
||||
.topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .topmenu-container.el-menu--horizontal>.el-submenu .el-submenu__title:hover {
|
||||
.topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,
|
||||
.topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,
|
||||
.topmenu-container.el-menu--horizontal>.el-submenu .el-submenu__title:hover {
|
||||
background-color: #ffffff !important;
|
||||
}
|
||||
|
||||
|
||||
204
src/components/contextMenu/index.vue
Normal file
@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<div class="context-menu-wrapper" @contextmenu.prevent="handleContextMenu($event)">
|
||||
<!-- 插槽:包裹需要绑定右键菜单的内容 -->
|
||||
<slot />
|
||||
|
||||
<!-- 右键菜单 -->
|
||||
<div v-if="visible" class="hospital-menu" :style="{
|
||||
top: `${top}px`,
|
||||
left: `${left}px`,
|
||||
display: visible ? 'block' : 'none',
|
||||
width: `${menuWidth}px`
|
||||
}" @click.stop @contextmenu.prevent>
|
||||
<template v-for="(item, index) in items" :key="index">
|
||||
<div v-if="item.type === 'divider'" class="menu-divider"></div>
|
||||
<div v-if="item.type !== 'divider'" class="menu-item" :class="{
|
||||
danger: item.danger,
|
||||
disabled: item.disabled
|
||||
}" @click="handleItemClick(item)">
|
||||
<span class="menu-shortcut" v-if="item.shortcut">{{ item.shortcut }}</span>
|
||||
<span class="menu-label">{{ item.label }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { ContextMenuItem } from '@/types/index';
|
||||
import emitter from '@/utils/mitt';
|
||||
|
||||
// 组件Props
|
||||
const props = withDefaults(defineProps<{
|
||||
items: ContextMenuItem[]; // 菜单项
|
||||
autoClose?: boolean; // 是否自动关闭菜单
|
||||
menuWidth?: number | string; // 菜单宽度
|
||||
}>(), {
|
||||
autoClose: true,
|
||||
menuWidth: 180,
|
||||
});
|
||||
|
||||
// 组件Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'select', item: ContextMenuItem): void;
|
||||
(e: 'open'): void;
|
||||
(e: 'close'): void;
|
||||
}>();
|
||||
|
||||
// 菜单状态
|
||||
const visible = ref(false);
|
||||
const top = ref(0);
|
||||
const left = ref(0);
|
||||
|
||||
|
||||
const handleContextMenu = async (e: MouseEvent) => {
|
||||
emitter.emit('closeAllContextMenus');
|
||||
|
||||
// 先计算初始位置
|
||||
left.value = Math.min(e.clientX, window.innerWidth - (typeof props.menuWidth === 'number' ? props.menuWidth : 180));
|
||||
top.value = e.clientY;
|
||||
visible.value = true;
|
||||
emit('open');
|
||||
|
||||
// 等待菜单渲染完成后获取实际高度
|
||||
await nextTick();
|
||||
const menuEl = document.querySelector('.hospital-menu') as HTMLElement;
|
||||
if (menuEl) {
|
||||
const menuHeight = menuEl.offsetHeight;
|
||||
const maxTop = window.innerHeight - menuHeight;
|
||||
// 确保菜单不会超出底部可视区域
|
||||
if (top.value > maxTop) {
|
||||
top.value = maxTop;
|
||||
// 如果向上调整后仍超出顶部,则取最小0值
|
||||
if (top.value < 0) top.value = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 处理菜单项点击
|
||||
const handleItemClick = (item: ContextMenuItem) => {
|
||||
if (item.disabled) return;
|
||||
emit('select', item);
|
||||
|
||||
|
||||
if (props.autoClose !== false) {
|
||||
hideMenu();
|
||||
}
|
||||
};
|
||||
|
||||
// 隐藏菜单
|
||||
const hideMenu = () => {
|
||||
visible.value = false;
|
||||
emit('close');
|
||||
};
|
||||
|
||||
// 点击外部区域关闭菜单
|
||||
const handleClickOutside = (e: MouseEvent) => {
|
||||
hideMenu();
|
||||
};
|
||||
|
||||
// 键盘事件处理
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (!visible.value) return;
|
||||
if (e.key === 'Escape') {
|
||||
hideMenu();
|
||||
}
|
||||
// 统一转换小写
|
||||
const row: ContextMenuItem | undefined = props.items.find(item => item.shortcut?.toLowerCase() === e.key?.toLowerCase());
|
||||
|
||||
if (row && !row.disabled) {
|
||||
handleItemClick(row)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
// 关闭所有菜单
|
||||
emitter.on('closeAllContextMenus', () => {
|
||||
if (visible.value) {
|
||||
hideMenu();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
|
||||
});
|
||||
|
||||
// 卸载时移除事件监听
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
emitter.off('closeAllContextMenus');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.context-menu-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.hospital-menu {
|
||||
position: fixed;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 .125rem .75rem rgba(0, 0, 0, 0.1);
|
||||
z-index: 9999;
|
||||
padding: .3125rem 0;
|
||||
font-size: .8125rem;
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
padding: .3125rem .625rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: background-color 0.2s;
|
||||
/* justify-content: space-between; */
|
||||
}
|
||||
|
||||
.menu-item:hover:not(.disabled) {
|
||||
background-color: #e6f7ff;
|
||||
color: #165DFF;
|
||||
}
|
||||
|
||||
.menu-item.disabled {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.menu-item i {
|
||||
margin-right: .5rem;
|
||||
font-size: .875rem;
|
||||
width: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.menu-divider {
|
||||
height: 1px;
|
||||
background-color: #e5e7eb;
|
||||
margin: .25rem 0;
|
||||
}
|
||||
|
||||
.menu-item.danger {
|
||||
color: #f53f3f;
|
||||
}
|
||||
|
||||
.menu-item.danger:hover:not(.disabled) {
|
||||
background-color: #fff1f0;
|
||||
color: #f53f3f;
|
||||
}
|
||||
|
||||
.menu-shortcut {
|
||||
color: #909399;
|
||||
margin-right: .3125rem;
|
||||
}
|
||||
</style>
|
||||
28
src/components/countTo/index.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<span>{{ showNum }}</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
|
||||
const props = defineProps<{ value: number }>()
|
||||
const showNum = ref(0)
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(val) => {
|
||||
let start = 0
|
||||
const step = val / 30
|
||||
const timer = setInterval(() => {
|
||||
start += step
|
||||
if (start >= val) {
|
||||
showNum.value = val
|
||||
clearInterval(timer)
|
||||
} else {
|
||||
showNum.value = Math.floor(start)
|
||||
}
|
||||
}, 30)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
</script>
|
||||
482
src/components/elTable/index.vue
Normal file
@ -0,0 +1,482 @@
|
||||
<template>
|
||||
<div class="custom-table-wrapper">
|
||||
<!-- 表格主体 -->
|
||||
<el-table ref="tableRef" :data="tableData" v-loading="loading" :stripe="config.stripe || false"
|
||||
:border="config.border" :fit="config.fit !== true" :show-header="config.showHeader !== false"
|
||||
:highlight-current-row="config.highlightCurrentRow || false" :row-class-name="config.rowClassName"
|
||||
:header-cell-style="config.headerCellStyle" :cell-style="config.cellStyle" :max-height="config.maxHeight"
|
||||
:show-summary="config.summary" :summary-method="getSummaries" :sum-text="config.sumText" :height="config.height"
|
||||
:row-key="config.key" :class="{ 'drag-table': enableRowDrag }" :size="config.size || 'default'"
|
||||
:empty-text="config.emptyText || '暂无数据'" @selection-change="handleSelectionChange"
|
||||
@current-change="handleCurrentChange" @row-click="handleRowClick"
|
||||
:header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" @row-dblclick="handleRowDblclick"
|
||||
@sort-change="handleSortChange" v-bind="$attrs">
|
||||
|
||||
<!-- 动态列 -->
|
||||
<template v-for="item in columns" :key="item.prop">
|
||||
<!-- 多选列 -->
|
||||
<el-table-column v-if="item.type == 'selection' && item.visible" type="selection" :width="item.width || 55"
|
||||
:fixed="item.fixed" :align="item.align || 'left'" />
|
||||
<!-- 序号列 -->
|
||||
<el-table-column v-if="item.type == 'index' && item.visible" type="index" class-name="el-table-column--index"
|
||||
:label="item.label || '序号'" :width="item.width || 60" :fixed="item.fixed" :align="item.align || 'left'"
|
||||
:index="getIndex" />
|
||||
|
||||
<!-- 自定义插槽列 行数据插槽(有row属性) -->
|
||||
<el-table-column v-if="!item.type && item.slot && item.visible" :prop="item.prop" :label="item.label"
|
||||
:width="item.width" :min-width="item.minWidth" :fixed="item.fixed" :align="item.align || 'left'"
|
||||
:sortable="item.sortable" :show-overflow-tooltip="item.showOverflowTooltip !== false">
|
||||
<template v-if="item.headerSlot" #header="scope">
|
||||
<slot :name="item.headerSlot" :column="scope.column" :$index="scope.$index" />
|
||||
</template>
|
||||
<template v-if="item.slot" #default="scope">
|
||||
<slot :name="item.slot" :row="scope.row" :$index="scope.$index" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 普通列 -->
|
||||
<el-table-column v-if="!item.type && !item.slot && item.visible" :prop="item.prop" :label="item.label"
|
||||
:width="item.width" :min-width="item.minWidth" :fixed="item.fixed" :align="item.align || 'left'"
|
||||
:sortable="item.sortable" :show-overflow-tooltip="item.showOverflowTooltip !== false"
|
||||
:formatter="item.formatter">
|
||||
<!-- 表头插槽 (无row属性)-->
|
||||
<template v-if="item.headerSlot" #header="scope">
|
||||
<slot :name="item.headerSlot" :column="scope.column" :$index="scope.$index" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<el-table-column v-if="$slots.action" :label="config.actionLabel || '操作'" :width="config.actionWidth"
|
||||
:min-width="config.actionMinWidth || 120" :fixed="config.actionFixed || 'right'"
|
||||
:align="config.actionAlign || 'center'">
|
||||
<template #default="scope">
|
||||
<slot name="action" :row="scope.row" :column="scope.column" :$index="scope.$index" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 空数据插槽 -->
|
||||
<template v-if="$slots.empty" #empty>
|
||||
<slot name="empty" />
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<div v-if="pagination.show" class="pagination-wrapper">
|
||||
<el-pagination v-model:current-page="currentPage" v-model:page-size="currentPageSize" :total="pagination.total"
|
||||
:size="aotuSize" :page-sizes="pagination.pageSizes || [10, 20, 50, 100]"
|
||||
:layout="pagination.layout || 'total, sizes, prev, pager, next, jumper'"
|
||||
:background="pagination.background !== false" :small="pagination.small || false"
|
||||
:disabled="pagination.disabled || false" @size-change="handleSizeChange"
|
||||
@current-change="handleCurrentPageChange" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch, PropType, onMounted } from "vue";
|
||||
import { TableColumnCtx } from 'element-plus';
|
||||
import { classCom } from "@/utils/classCom";
|
||||
const aotuSize = classCom.useAutoSize();
|
||||
// @ts-ignore
|
||||
import Sortable from 'sortablejs'; // 引入sortablejs
|
||||
interface TableColumn {
|
||||
prop?: string;
|
||||
type?: string; // 'selection' | 'index' | undefined
|
||||
key?: string | number;
|
||||
label?: string;
|
||||
width?: string | number;
|
||||
minWidth?: string | number;
|
||||
fixed?: boolean | string;
|
||||
align?: string;
|
||||
sortable?: boolean;
|
||||
showOverflowTooltip?: boolean;
|
||||
formatter?: Function;
|
||||
slot?: string;
|
||||
headerSlot?: string;
|
||||
visible?: boolean; // 是否显示列
|
||||
}
|
||||
|
||||
// 在子组件中定义插槽类型
|
||||
defineSlots<{
|
||||
// 具名插槽和动态插槽(不含 default)
|
||||
[slotName: string]: (props: { row?: any; column?: any; $index?: number }) => any;
|
||||
}>();
|
||||
|
||||
// Props 定义
|
||||
const props = defineProps({
|
||||
// 表格数据
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
// 表格列配置
|
||||
columns: {
|
||||
type: Array as PropType<TableColumn[]>,
|
||||
default: () => [],
|
||||
},
|
||||
// 表格配置
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 加载状态
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 分页配置
|
||||
pagination: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
show: false,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
}),
|
||||
},
|
||||
// 拖拽列
|
||||
enableColumnDrag: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 拖拽行
|
||||
enableRowDrag: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Emits 定义
|
||||
const emit = defineEmits([
|
||||
"selection-change",
|
||||
"current-change",
|
||||
"row-click",
|
||||
"row-dblclick",
|
||||
"sort-change",
|
||||
"page-change",
|
||||
"size-change",
|
||||
"column-drag-end",
|
||||
"row-drag-end"
|
||||
]);
|
||||
|
||||
// 响应式数据
|
||||
const tableRef = ref();
|
||||
const currentPage = ref(props.pagination.currentPage || 1); // 第几页
|
||||
const currentPageSize = ref(props.pagination.pageSize || 10); // 一页显示多少条
|
||||
|
||||
// 计算属性
|
||||
const tableData = computed(() => {
|
||||
if (props.pagination.show && props.pagination.clientPaging) {
|
||||
// 客户端分页
|
||||
const start = (currentPage.value - 1) * currentPageSize.value;
|
||||
const end = start + currentPageSize.value;
|
||||
return props.data.slice(start, end);
|
||||
}
|
||||
return props.data;
|
||||
});
|
||||
|
||||
// 序号计算
|
||||
const getIndex = (index: number) => {
|
||||
if (props.pagination.show && !props.pagination.clientPaging) {
|
||||
return (currentPage.value - 1) * currentPageSize.value + index + 1;
|
||||
}
|
||||
return index + 1;
|
||||
};
|
||||
|
||||
// const headerCellClassName = (column: TableColumnCtx<any>) => {
|
||||
// if (!column.column.property) {
|
||||
// return ''; // 不添加类名
|
||||
// } else {
|
||||
// return 'el-table-header-cell'; // 添加自定义类名
|
||||
// }
|
||||
// };
|
||||
|
||||
// 计算列合计
|
||||
// 自定义汇总方法 - 只计算指定列
|
||||
const getSummaries = ({ columns, data }: { columns: any, data: any }) => {
|
||||
const summaries = columns.map(() => '');
|
||||
if (props.config.summaryField.length > 0) {
|
||||
props.config.summaryField.forEach((v: any) => {
|
||||
const index = columns.find((column: any) => column.property === v)?.no;
|
||||
const summaryData = data.map((item: any) => item[v]);
|
||||
const summary = summaryData.reduce((acc: any, cur: any) => Number(acc) + Number(cur), 0);
|
||||
summaries[index] = summary;
|
||||
});
|
||||
summaries[0] = props.config.sumText;
|
||||
}
|
||||
|
||||
return summaries;
|
||||
};
|
||||
// 事件处理
|
||||
const handleSelectionChange = (selection: any[]) => {
|
||||
emit("selection-change", selection);
|
||||
};
|
||||
|
||||
const handleCurrentChange = (currentRow: any, oldCurrentRow: any) => {
|
||||
emit("current-change", currentRow, oldCurrentRow);
|
||||
};
|
||||
|
||||
const handleRowClick = (row: any, column: TableColumnCtx<any>, event: Event) => {
|
||||
emit("row-click", row, column, event);
|
||||
};
|
||||
|
||||
const handleRowDblclick = (row: any, column: TableColumnCtx<any>, event: Event) => {
|
||||
emit("row-dblclick", row, column, event);
|
||||
};
|
||||
|
||||
const handleSortChange = (sortInfo: Object) => {
|
||||
emit("sort-change", sortInfo);
|
||||
};
|
||||
|
||||
const handleSizeChange = (size: number) => {
|
||||
currentPageSize.value = size;
|
||||
currentPage.value = 1;
|
||||
emit("size-change", {
|
||||
pageSize: size,
|
||||
currentPage: 1,
|
||||
});
|
||||
};
|
||||
|
||||
const handleCurrentPageChange = (page: number) => {
|
||||
currentPage.value = page;
|
||||
emit("page-change", {
|
||||
currentPage: page,
|
||||
pageSize: currentPageSize.value,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 初始化列拖拽功能
|
||||
onMounted(() => {
|
||||
if (props.enableColumnDrag && tableRef.value) {
|
||||
initColumnDrag();
|
||||
}
|
||||
if (props.enableRowDrag && tableRef.value) {
|
||||
initRowDrag();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 监听分页配置变化
|
||||
watch(
|
||||
() => props.pagination.currentPage,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
currentPage.value = newVal;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
|
||||
watch(
|
||||
() => props.pagination.pageSize,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
currentPageSize.value = newVal;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
// 初始化列拖拽
|
||||
const initColumnDrag = () => {
|
||||
// 获取表头单元格
|
||||
const tableHeader = tableRef.value.$el.querySelector('.el-table__header-wrapper thead tr');
|
||||
if (!tableHeader) return;
|
||||
// 初始化拖拽
|
||||
const sortable = new Sortable(tableHeader, {
|
||||
animation: 150, // 动画时间
|
||||
handle: '.el-table-header-cell', // 拖拽手柄
|
||||
ghostClass: 'sortable-ghost', // 拖拽时的占位符样式
|
||||
// filter: '.el-table-column--selection, .el-table-column--index', // 排除选择列和序号列
|
||||
onEnd: (evt: any) => {
|
||||
// console.log('evt==>', evt);
|
||||
// 排除固定列和选择列、序号列
|
||||
const visibleColumns = props.columns.filter(col => col.visible !== false);
|
||||
|
||||
// 过滤掉固定列
|
||||
const draggableColumns = visibleColumns.filter(col => !col.fixed);
|
||||
|
||||
// 如果发生了位置变化
|
||||
if (evt.oldIndex !== evt.newIndex && draggableColumns.length) {
|
||||
// 复制原数组并调整顺序
|
||||
const newColumns = [...draggableColumns];
|
||||
const [movedItem] = newColumns.splice(evt.oldIndex, 1);
|
||||
newColumns.splice(evt.newIndex, 0, movedItem);
|
||||
|
||||
// 更新原始columns数组中对应列的位置
|
||||
const updatedColumns = [...props.columns];
|
||||
// 先移除所有可拖拽列
|
||||
const nonDraggableColumns = updatedColumns.filter(col => col.fixed);
|
||||
// 合并固定列和新顺序的可拖拽列
|
||||
const resultColumns = nonDraggableColumns.concat(newColumns);
|
||||
|
||||
// 触发事件,通知父组件列顺序已改变
|
||||
emit('column-drag-end', {
|
||||
oldIndex: evt.oldIndex,
|
||||
newIndex: evt.newIndex,
|
||||
columns: resultColumns
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 初始化行拖拽
|
||||
const initRowDrag = () => {
|
||||
const tableBody = tableRef.value.$el.querySelector('.el-table__body-wrapper tbody');
|
||||
const sortable = new Sortable(tableBody, {
|
||||
animation: 150, // 拖拽动画时长
|
||||
ghostClass: 'sortable-ghost', // 拖拽占位符样式
|
||||
chosenClass: 'sortable-chosen', // 选中行样式
|
||||
// 拖拽结束回调
|
||||
onEnd: (evt: any) => {
|
||||
const { oldIndex, newIndex } = evt
|
||||
if (oldIndex === newIndex) return // 未改变位置则不处理
|
||||
|
||||
// 调整数组顺序
|
||||
const moveRow = tableData.value.splice(oldIndex, 1)[0]
|
||||
tableData.value.splice(newIndex, 0, moveRow)
|
||||
|
||||
// 重新更新排序值
|
||||
tableData.value.forEach((item: any, index) => {
|
||||
item.sort = index + 1
|
||||
})
|
||||
// console.log("🚀 ~ initRowDrag ~ tableData.value:", tableData.value)
|
||||
emit('row-drag-end', {
|
||||
oldIndex,
|
||||
newIndex,
|
||||
list: tableData.value
|
||||
})
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// 暴露方法
|
||||
const clearSelection = () => {
|
||||
tableRef.value?.clearSelection();
|
||||
};
|
||||
|
||||
const toggleRowSelection = (row: Object, selected: boolean) => {
|
||||
tableRef.value?.toggleRowSelection(row, selected);
|
||||
};
|
||||
|
||||
const getSelectionRows = () => {
|
||||
return tableRef.value?.getSelectionRows() || [];
|
||||
};
|
||||
|
||||
const toggleAllSelection = () => {
|
||||
tableRef.value?.toggleAllSelection();
|
||||
};
|
||||
|
||||
const setCurrentRow = (row: Object) => {
|
||||
tableRef.value?.setCurrentRow(row);
|
||||
};
|
||||
|
||||
const setScrollTo = (top: number) => {
|
||||
tableRef.value?.scrollTo(top);
|
||||
};
|
||||
|
||||
const setScrollTop = (index: number) => {
|
||||
tableRef.value?.setScrollTop(index * 30); //30px/行
|
||||
};
|
||||
|
||||
const clearSort = () => {
|
||||
tableRef.value?.clearSort();
|
||||
};
|
||||
|
||||
const doLayout = () => {
|
||||
tableRef.value?.doLayout();
|
||||
};
|
||||
|
||||
const sort = (prop: string, order: any) => {
|
||||
tableRef.value?.sort(prop, order);
|
||||
};
|
||||
|
||||
// 导出方法
|
||||
defineExpose({
|
||||
clearSelection,
|
||||
toggleRowSelection,
|
||||
getSelectionRows,
|
||||
toggleAllSelection,
|
||||
setCurrentRow,
|
||||
setScrollTo,
|
||||
setScrollTop,
|
||||
clearSort,
|
||||
doLayout,
|
||||
sort,
|
||||
tableRef,
|
||||
initColumnDrag
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-table-wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// 只在拖拽手柄上显示移动光标
|
||||
:deep(.el-table-header-cell .cell) {
|
||||
cursor: move;
|
||||
/* 恢复默认光标 */
|
||||
}
|
||||
|
||||
// 拖拽手柄样式(使用排序图标作为拖拽手柄)
|
||||
:deep(.el-table-header-cell .sort-caret) {
|
||||
// cursor: move;
|
||||
/* 只在排序图标处显示移动光标 */
|
||||
// margin-left: 1px;
|
||||
}
|
||||
|
||||
// 保留列宽调整的光标样式
|
||||
:deep(.el-table__header-wrapper .el-table__header tr th .el-table__header-drag-icon) {
|
||||
cursor: col-resize !important;
|
||||
}
|
||||
|
||||
|
||||
:deep(.el-table__footer-wrapper tfoot td.el-table__cell) {
|
||||
color: #1f6dd3 !important;
|
||||
font-weight: 700;
|
||||
/* 可替换为任意颜色值 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.pagination-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: .3125rem 0;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
// /* 修改选中行背景色 */
|
||||
// ::v-deep .el-table__body tr.current-row>td {
|
||||
// background-color: #a4beef !important;
|
||||
// }
|
||||
|
||||
// /* 可选:修改悬停颜色 */
|
||||
// ::v-deep .el-table__body tr.hover-row>td {
|
||||
// background-color: #a4beef !important;
|
||||
// }
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.pagination-wrapper {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pagination-wrapper :deep(.el-pagination) {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,10 +1,6 @@
|
||||
<template>
|
||||
<div v-loading="loading" :style="'height:' + height">
|
||||
<iframe
|
||||
:src="url"
|
||||
frameborder="no"
|
||||
style="width: 100%; height: 100%"
|
||||
scrolling="auto" />
|
||||
<iframe :src="url" frameborder="no" style="width: 100%; height: 100%" scrolling="auto" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
165
src/components/projectDetails/index.vue
Normal file
@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<div class="dict-input-wrapper">
|
||||
<!-- 字典选择弹窗 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="30vw" :close-on-click-modal="false" :draggable="true"
|
||||
@close="handleDialogClose">
|
||||
<el-input ref="inputRef" v-model="searchKey" placeholder="搜索(支持名称、编码、简拼)..." class="mb10" clearable
|
||||
@clear="filterDictData" @input="filterDictData" />
|
||||
|
||||
<el-table :data="filteredDictData" height="300px" border @row-dblclick="selectItem" highlight-current-row>
|
||||
<el-table-column prop="value" label="编码" align="center" width="150" />
|
||||
<el-table-column prop="label" label="名称" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="pinyin" label="简拼" align="center" width="100" /> <!-- 显示简拼便于调试 -->
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import { queryXmInfo } from '@/api/liswork/work/LisWork'
|
||||
import { getFirstLetter } from '@/utils/pinyin'; // 引入拼音处理工具
|
||||
// 组件参数
|
||||
const props = defineProps({
|
||||
modelValue: { type: [String, Number], default: '' },
|
||||
dictType: { type: String },
|
||||
placeholder: { type: String, default: '请输入或双击选择' },
|
||||
clearable: { type: Boolean, default: true },
|
||||
disabled: { type: Boolean, default: false },
|
||||
dialogTitle: { type: String, default: '选择字典项' },
|
||||
tableKey: { type: Object, default: () => { } },
|
||||
});
|
||||
|
||||
// 组件事件
|
||||
const emit = defineEmits(['select']);
|
||||
|
||||
|
||||
const dictData = ref([]); // 存储带简拼的字典数据
|
||||
const filteredDictData = ref([]);
|
||||
const isDictLoading = ref(false);
|
||||
const dialogVisible = ref(false);
|
||||
const searchKey = ref('');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 加载字典数据(并添加简拼字段)
|
||||
const loadDictData = async () => {
|
||||
try {
|
||||
isDictLoading.value = true;
|
||||
const requestParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 1000, // 加载足够多的项目
|
||||
yq: props.tableKey.yq, // 当前选中的仪器
|
||||
};
|
||||
const response = await queryXmInfo(requestParams);
|
||||
|
||||
const rawData = response.data.map((item: any, index: number) => {
|
||||
return {
|
||||
value: item.xmdh || `未知编码_${index}`, // 确保value存在
|
||||
label: item.xmmc || `未知名称_${index}`, // 确保label存在
|
||||
dw: item.dw || "",
|
||||
refs: item.refs || "",
|
||||
};
|
||||
});
|
||||
// 为每个字典项添加简拼字段
|
||||
dictData.value = (rawData || []).map((item: any) => ({
|
||||
...item,
|
||||
pinyin: getFirstLetter(item.label) // 新增pinyin字段存储简拼
|
||||
}));
|
||||
|
||||
filteredDictData.value = [...dictData.value];
|
||||
} catch (error) {
|
||||
console.error(`加载${props.dictType}字典失败:`, error);
|
||||
dictData.value = [];
|
||||
filteredDictData.value = [];
|
||||
} finally {
|
||||
isDictLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 核心搜索逻辑(支持模糊搜索+简拼搜索)
|
||||
const filterDictData = () => {
|
||||
const key = searchKey.value.trim().toLowerCase();
|
||||
if (!key) {
|
||||
filteredDictData.value = [...dictData.value];
|
||||
return;
|
||||
}
|
||||
|
||||
filteredDictData.value = dictData.value.filter((item: any) => {
|
||||
// 1. 模糊搜索:匹配label(名称)或value(编码)
|
||||
const matchLabel = item.label.toLowerCase().includes(key);
|
||||
const matchValue = String(item.value).toLowerCase().includes(key);
|
||||
|
||||
// 2. 简拼搜索:匹配首字母简拼
|
||||
const matchPinyin = item.pinyin.toLowerCase().includes(key);
|
||||
|
||||
// 满足任一条件即匹配
|
||||
return matchLabel || matchValue || matchPinyin;
|
||||
});
|
||||
};
|
||||
|
||||
const inputRef = ref()
|
||||
// 关键修改:打开弹窗时重新加载数据
|
||||
const openDictSelector = async () => {
|
||||
if (props.disabled || isDictLoading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 打开弹窗前先加载数据(确保每次打开都是最新的)
|
||||
await loadDictData();
|
||||
|
||||
// 数据加载完成后再显示弹窗
|
||||
dialogVisible.value = true;
|
||||
searchKey.value = '';
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
inputRef.value.focus();
|
||||
}, 100);
|
||||
});
|
||||
filterDictData();
|
||||
};
|
||||
|
||||
|
||||
// 选择字典项
|
||||
const selectItem = (item: any) => {
|
||||
emit('select', item);
|
||||
dialogVisible.value = false;
|
||||
};
|
||||
|
||||
|
||||
const handleDialogClose = () => {
|
||||
dialogVisible.value = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
defineExpose({
|
||||
openDictSelector, // 暴露打开弹窗的方法
|
||||
// 可选:暴露其他可能需要的方法(如刷新字典数据)
|
||||
loadDictData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 样式保持不变 */
|
||||
.dict-input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.select-icon:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
:deep(.el-input__suffix) {
|
||||
gap: 4px;
|
||||
}
|
||||
</style>
|
||||
108
src/components/projectsjg/index.vue
Normal file
@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog :title="dialogTitle" v-model="csjgVisible" width="300px" :close-on-click-modal="false" :draggable="true">
|
||||
<el-input ref="inputRef" v-model="searchKey" :placeholder="placeholder" size="small" class="mb10" clearable
|
||||
@clear="filterDictData" @input="filterDictData" />
|
||||
|
||||
<el-table :data="filterData" max-height="300px" border @row-dblclick="selectItem" highlight-current-row
|
||||
:row-style="{ helght: '25px' }">
|
||||
<el-table-column prop="qz" label="取值" align="center" />
|
||||
<el-table-column prop="pinyin" label="简拼" align="center" />
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch, computed, reactive, toRaw } from 'vue';
|
||||
import { getFirstLetter } from '@/utils/pinyin';
|
||||
|
||||
|
||||
interface Props {
|
||||
tableData: object[];
|
||||
label?: string;
|
||||
dialogTitle?: string;
|
||||
placeholder?: string;
|
||||
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
label: undefined,
|
||||
dialogTitle: '选择数据',
|
||||
placeholder: '支持简拼搜索'
|
||||
});
|
||||
const csjgVisible = ref(false)
|
||||
const searchKey = ref('')
|
||||
const filterData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||
const filterDictData = () => {
|
||||
const key = searchKey.value.trim().toLowerCase();
|
||||
|
||||
if (!key) {
|
||||
// 空搜索时显示全部预处理数据
|
||||
filterData.value = [...processedTableData.value];
|
||||
return;
|
||||
}
|
||||
|
||||
filterData.value = processedTableData.value.filter((item: any) => {
|
||||
// 1. 原文本匹配
|
||||
const matchLabel = props.label && item[props.label]?.toString().toLowerCase().includes(key);
|
||||
return matchLabel;
|
||||
});
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: "selectItem", val: any): void;
|
||||
}
|
||||
const emits = defineEmits<Emits>();
|
||||
const selectItem = (row: any) => {
|
||||
emits('selectItem', row);
|
||||
csjgVisible.value = false;
|
||||
}
|
||||
// 存储预处理后的带拼音数据
|
||||
const processedTableData = ref<{ [key: string]: any; pinyinMap: Record<string, string> }[]>([]);
|
||||
// 初始化数据
|
||||
onMounted(() => {
|
||||
processedTableData.value = processTableData(props.tableData);
|
||||
|
||||
filterData.value = [...processedTableData.value];
|
||||
});
|
||||
|
||||
// 监听表格数据变化,重新处理
|
||||
watch(() => props.tableData, (newVal) => {
|
||||
processedTableData.value = processTableData(newVal);
|
||||
filterData.value = [...processedTableData.value];
|
||||
// 数据回显
|
||||
}, { deep: true });
|
||||
// 预处理数据:生成拼音信息
|
||||
const processTableData = (data: object[]) => {
|
||||
return data.map((item: any) => {
|
||||
const pinyinMap: Record<string, string> = {};
|
||||
// 处理label字段拼音
|
||||
if (props.label) {
|
||||
pinyinMap['pinyin'] = getFirstLetter(item[props.label]).toLowerCase();
|
||||
return { ...item, ...pinyinMap };
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
const inputRef = ref()
|
||||
const open = () => {
|
||||
csjgVisible.value = true;
|
||||
nextTick(() => {
|
||||
searchKey.value = '';
|
||||
setTimeout(() => {
|
||||
inputRef.value.focus();
|
||||
}, 100);
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table .el-table__cell) {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
274
src/components/selectSearch/index.vue
Normal file
@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<el-popover :visible="selectVisible" placement="bottom" :width="'18vw'" @after-enter="initClickOutside">
|
||||
<el-form :model="queryParams" class="query-form" label-width="5.625rem">
|
||||
<!-- 病人类型选择 -->
|
||||
<el-form-item label="病人类型:" prop="brly">
|
||||
<el-select v-model="queryParams.brly" placeholder="全部" clearable>
|
||||
<el-option v-for="item in brlyOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="完成状态:" prop="finish">
|
||||
<el-radio-group v-model="queryParams.finish" @change="handleRadioChange">
|
||||
<el-radio value="1" @click.native="handleRadioClick('1', 'finish')">已完成</el-radio>
|
||||
<el-radio value="0" @click.native="handleRadioClick('0', 'finish')">未完成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<!-- 审核状态选择 -->
|
||||
<el-form-item label="审核状态:" prop="jgbz">
|
||||
<el-radio-group v-model="queryParams.jgbz" @change="handleRadioChange">
|
||||
<el-radio value="2" @click.native="handleRadioClick('2', 'jgbz')">已审核</el-radio>
|
||||
<el-radio value="0" @click.native="handleRadioClick('0', 'jgbz')">未审核</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<!-- 自审状态选择 -->
|
||||
<el-form-item label-width="0.625" prop="autojgbz">
|
||||
<el-checkbox v-model="queryParams.autojgbz" true-value="1" false-value=""> 自审 </el-checkbox>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- 危急值选择 -->
|
||||
<el-form-item prop="alarmflag" label-width="0">
|
||||
<el-checkbox v-model="queryParams.alarmflag" true-value="1" false-value=""> 危急值 </el-checkbox>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- 急诊选择 -->
|
||||
<el-form-item prop="jzbz" label-width="0">
|
||||
<el-checkbox v-model="queryParams.jzbz" true-value="1" false-value=""> 急诊 </el-checkbox>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 打印状态选择 -->
|
||||
<el-form-item label="打印状态:" prop="dybz">
|
||||
<el-radio-group v-model="queryParams.dybz" @chnage="handleRadioChange">
|
||||
<el-radio value="1" @click.native="handleRadioClick('1', 'dybz')">已打印</el-radio>
|
||||
<el-radio value="0" @click.native="handleRadioClick('0', 'dybz')">未打印</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery" :size="props.size">确认查询</el-button>
|
||||
<el-button @click="handleReset" style="margin-left: 0.5rem" :size="props.size">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #reference>
|
||||
<el-input v-model="selectShowValue" :size="props.size" @clear="clearHandle"
|
||||
@click="selectVisible = !selectVisible" :placeholder="props.placeholder" readonly
|
||||
:style="{ width: props.width }" suffix-icon="ArrowDown" :clearable="props.clearable" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
// 定义下拉选项类型
|
||||
interface OptionItem {
|
||||
label: string
|
||||
value: string | number
|
||||
}
|
||||
|
||||
// 定义查询参数类型
|
||||
interface QueryParams {
|
||||
brly?: string | number
|
||||
jgbz?: string | number
|
||||
dybz?: string | number
|
||||
alarmflag?: string | number
|
||||
jzbz?: string | number
|
||||
finish?: string | number
|
||||
autojgbz?: string | number
|
||||
}
|
||||
|
||||
// 定义组件Props
|
||||
const props = defineProps<{
|
||||
// 可传入初始查询参数
|
||||
initialParams?: Partial<QueryParams>,
|
||||
// 宽度
|
||||
width?: string,
|
||||
// 是否禁用
|
||||
disabled?: boolean,
|
||||
// 是否可清空
|
||||
clearable?: boolean,
|
||||
// 是否显示查询按钮
|
||||
showQueryButton?: boolean,
|
||||
// 是否显示重置按钮
|
||||
showResetButton?: boolean,
|
||||
// 尺寸
|
||||
size?: 'large' | 'default' | 'small',
|
||||
// 占位符
|
||||
placeholder?: string,
|
||||
dictData?: any
|
||||
}>()
|
||||
|
||||
|
||||
watch(() => props.dictData, () => {
|
||||
brlyOptions.value = props.dictData.PT
|
||||
optionMaps.brly = props.dictData.PT
|
||||
})
|
||||
|
||||
// 定义组件事件
|
||||
const emit = defineEmits<{
|
||||
// 查询事件,返回查询参数
|
||||
(e: 'query', params: QueryParams): void
|
||||
// 重置事件
|
||||
(e: 'reset'): void
|
||||
}>()
|
||||
const selectVisible = ref(false)
|
||||
const selectShowValue = ref('')
|
||||
const selectRef = ref()
|
||||
// 病人类型选项
|
||||
const brlyOptions = ref<OptionItem[]>([])
|
||||
// 审核状态选项
|
||||
const jgbzOptions: OptionItem[] = [
|
||||
{ label: '未审核', value: 0 },
|
||||
{ label: '已审核', value: 2 },
|
||||
]
|
||||
|
||||
// 打印状态选项
|
||||
const dybzOptions: OptionItem[] = [
|
||||
{ label: '未打印', value: 0 },
|
||||
{ label: '已打印', value: 1 },
|
||||
]
|
||||
|
||||
// 危急值选项
|
||||
const alarmflagOptions: OptionItem[] = [
|
||||
{ label: '危急值', value: 1 },
|
||||
{ label: '无', value: 0 }
|
||||
]
|
||||
|
||||
// 急诊选项
|
||||
const emergencyOptions: OptionItem[] = [
|
||||
{ label: '急诊', value: 1 },
|
||||
{ label: '否', value: 0 }
|
||||
]
|
||||
|
||||
// 完成状态选项
|
||||
const finishOptions: OptionItem[] = [
|
||||
{ label: '未完成', value: 0 },
|
||||
{ label: '已完成', value: 1 },
|
||||
]
|
||||
|
||||
// 自审状态选项
|
||||
const autojgbzOptions: OptionItem[] = [
|
||||
{ label: '否', value: 0 },
|
||||
{ label: '自审', value: 1 },
|
||||
]
|
||||
|
||||
|
||||
// 创建选项映射关系,方便查找label
|
||||
const optionMaps = {
|
||||
brly: props.dictData.PT,
|
||||
jgbz: jgbzOptions,
|
||||
dybz: dybzOptions,
|
||||
alarmflag: alarmflagOptions,
|
||||
jzbz: emergencyOptions,
|
||||
finish: finishOptions,
|
||||
autojgbz: autojgbzOptions
|
||||
}
|
||||
|
||||
// 查询参数
|
||||
const queryParams = ref<QueryParams>({
|
||||
...props.initialParams
|
||||
})
|
||||
|
||||
// 由于更多按钮在 app 元素内,给 app 元素注册的点击事件必须在弹出框显示后并且是一次性的
|
||||
// 防止更多按钮的事件与之冲突
|
||||
const initClickOutside = () => {
|
||||
document.getElementById('app')!.addEventListener('click', () => {
|
||||
selectVisible.value = false
|
||||
}, { once: true })
|
||||
}
|
||||
|
||||
// 记录上一次选中的值
|
||||
const lastRadioValue = ref<string | undefined>(undefined);
|
||||
const handleRadioChange = (value: string) => {
|
||||
lastRadioValue.value = value;
|
||||
};
|
||||
const handleRadioClick = (value: string, zd: keyof QueryParams) => {
|
||||
if (value === lastRadioValue.value) {
|
||||
setTimeout(() => {
|
||||
queryParams.value[zd] = undefined;
|
||||
lastRadioValue.value = undefined;
|
||||
}, 100);
|
||||
} else {
|
||||
lastRadioValue.value = value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const clearHandle = () => {
|
||||
queryParams.value = {}
|
||||
selectShowValue.value = ''
|
||||
}
|
||||
|
||||
// 根据值和选项列表获取对应的label
|
||||
const getLabelByValue = (value: string | number | undefined, options: OptionItem[]) => {
|
||||
if (value === undefined || value === null || value === '') return ''
|
||||
const item = options.find(option => option.value == value)
|
||||
return item ? item.label : ''
|
||||
}
|
||||
|
||||
// 处理查询
|
||||
const handleQuery = () => {
|
||||
// 过滤空值参数
|
||||
const filteredParams = Object.fromEntries(
|
||||
Object.entries(queryParams.value).filter(([_, v]) => v !== undefined && v !== null && v !== '')
|
||||
) as QueryParams
|
||||
|
||||
// 收集所有选中项的label
|
||||
const labels: string[] = []
|
||||
Object.entries(filteredParams).forEach(([key, value]) => {
|
||||
// @ts-ignore
|
||||
const options = optionMaps[key]
|
||||
if (options) {
|
||||
const label = getLabelByValue(value, options)
|
||||
if (label) labels.push(label)
|
||||
}
|
||||
})
|
||||
|
||||
// 拼接label并设置到显示值
|
||||
selectShowValue.value = labels.join(',')
|
||||
console.log('selectShowValue.value==>', selectShowValue.value);
|
||||
|
||||
emit('query', filteredParams)
|
||||
|
||||
selectVisible.value = false;
|
||||
}
|
||||
|
||||
// 处理重置
|
||||
const handleReset = () => {
|
||||
selectShowValue.value = ''
|
||||
queryParams.value = {}
|
||||
selectVisible.value = false;
|
||||
emit('reset')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.query-form {
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 768px) {
|
||||
.query-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
189
src/components/tabViews/index.vue
Normal file
@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div class="tab-container">
|
||||
<el-icon class="scroll-btn left" @click="scrollAndSelect('left')" :disabled="!hasLeftScroll">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<div class="tab-wrapper">
|
||||
<div class="tab-list" ref="tabListRef" @scroll="handleScroll">
|
||||
<div :class="['text', activeTab === item.value ? 'active' : '']" v-for="item in tabList" :key="item.value"
|
||||
@click="handleTabClick(item.value)" ref="tabItems">
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-icon class="scroll-btn right" @click="scrollAndSelect('right')" :disabled="!hasRightScroll">
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
|
||||
|
||||
// 定义 tabList 元素的类型
|
||||
interface TabItem {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
tabList: TabItem[];
|
||||
activeTab: string | number;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:activeTab']);
|
||||
|
||||
const tabListRef = ref();
|
||||
const tabItems = ref<HTMLDivElement[]>([]);
|
||||
const hasLeftScroll = ref(false);
|
||||
const hasRightScroll = ref(false);
|
||||
|
||||
|
||||
const handleScroll = () => {
|
||||
if (tabListRef.value) {
|
||||
const { scrollLeft, scrollWidth, clientWidth } = tabListRef.value;
|
||||
hasLeftScroll.value = scrollLeft > 5;
|
||||
hasRightScroll.value = scrollLeft < scrollWidth - clientWidth - 5;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleTabClick = (value: any) => {
|
||||
emit('update:activeTab', value);
|
||||
scrollToActiveTab();
|
||||
};
|
||||
|
||||
// 滚动到当前激活的Tab
|
||||
const scrollToActiveTab = () => {
|
||||
if (!tabListRef.value) return;
|
||||
|
||||
const activeIndex = props.tabList.findIndex((item: any) => item.value === props.activeTab);
|
||||
if (activeIndex === -1) return;
|
||||
|
||||
const activeTabElement = tabItems.value[activeIndex];
|
||||
if (activeTabElement) {
|
||||
const scrollContainer = tabListRef.value;
|
||||
const containerRect = scrollContainer.getBoundingClientRect();
|
||||
const tabRect = activeTabElement.getBoundingClientRect();
|
||||
|
||||
// 如果Tab不在可见区域内,则滚动到可见区域
|
||||
if (tabRect.left < containerRect.left || tabRect.right > containerRect.right) {
|
||||
scrollContainer.scrollTo({
|
||||
left: tabRect.left - containerRect.left + scrollContainer.scrollLeft - 200,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 滚动并选中
|
||||
const scrollAndSelect = (direction: 'left' | 'right') => {
|
||||
if (!tabListRef.value || tabItems.value.length === 0) return;
|
||||
|
||||
const currentIndex = props.tabList.findIndex((item: any) => item.value === props.activeTab);
|
||||
let newIndex;
|
||||
|
||||
if (direction === 'left') {
|
||||
// 向左滚动并选中前一个Tab
|
||||
newIndex = currentIndex > 0 ? currentIndex - 1 : 0;
|
||||
} else {
|
||||
// 向右滚动并选中后一个Tab
|
||||
newIndex = currentIndex < props.tabList.length - 1 ? currentIndex + 1 : props.tabList.length - 1;
|
||||
}
|
||||
|
||||
emit('update:activeTab', props.tabList[newIndex].value);
|
||||
};
|
||||
|
||||
// 监听activeTab变化,确保滚动到可视区域
|
||||
watch(() => props.activeTab, scrollToActiveTab);
|
||||
|
||||
// 初始化时检查滚动状态
|
||||
setTimeout(() => {
|
||||
handleScroll();
|
||||
}, 0);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tab-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.scroll-btn {
|
||||
width: 1.875rem;
|
||||
height: 2.9375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.1);
|
||||
transition: opacity 0.3s;
|
||||
|
||||
&.left {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: .75rem 0 0 .75rem;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
&.right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
border-radius: 0 .75rem .75rem 0;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-wrapper {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
padding: 0 1.875rem; // 给箭头留出空间
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
display: flex;
|
||||
gap: 1px;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 1px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none; // 隐藏滚动条
|
||||
-ms-overflow-style: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none; // 隐藏滚动条
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
font-weight: 400;
|
||||
font-size: 1rem;
|
||||
color: #1F6DD3;
|
||||
width: 5.625rem;
|
||||
height: 2.9375rem;
|
||||
line-height: 2.9375rem;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: #e9f1fb;
|
||||
color: #1F6DD3;
|
||||
font-weight: 600;
|
||||
font-family: SourceHanSansCN, SourceHanSansCN;
|
||||
}
|
||||
</style>
|
||||
113
src/components/userVerification/index.vue
Normal file
@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog v-model="visible" :title="title" :width="500" :close-on-click-modal="false" :draggable="true">
|
||||
<el-form ref="formRef" :model="formData" label-width="100px">
|
||||
<!-- 用户代号 -->
|
||||
<el-form-item label="用户代号:" prop="yhdh" :rules="[{ required: true, message: '请输入用户代号', trigger: 'change' }]">
|
||||
<el-input ref="yhdhRef" v-model="formData.yhdh" @change="handleChange" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 用户姓名 -->
|
||||
<el-form-item label="用户姓名:">
|
||||
<el-input v-model="formData.userName" disabled />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 密码输入 -->
|
||||
<el-form-item label="密码:" prop="mm" :rules="[{ required: true, message: '请输入密码', trigger: 'change' }]">
|
||||
<el-input v-model="formData.mm" type="password" @keyup.enter="handleConfirm" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer" style="text-align: center;">
|
||||
<el-button type="primary" @click="handleConfirm"> 确定 </el-button>
|
||||
<el-button @click="cancel"> 取消 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { checkYsUser } from '@/api/liswork/work/LisWork'
|
||||
interface UserInfo {
|
||||
usenName: string,
|
||||
nickName: string,
|
||||
}
|
||||
const props = defineProps({
|
||||
|
||||
labPatKey: {
|
||||
type: Object,
|
||||
default: () => { }
|
||||
},
|
||||
userList: {
|
||||
type: Array as PropType<UserInfo[]>,
|
||||
default: () => []
|
||||
},
|
||||
|
||||
title: {
|
||||
type: String,
|
||||
default: '请输入锁定人员账号密码'
|
||||
}
|
||||
});
|
||||
const visible = ref(false);
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
yhdh: '',
|
||||
userName: '',
|
||||
mm: '',
|
||||
})
|
||||
|
||||
const formRef = ref();
|
||||
const yhdhRef = ref();
|
||||
const open = () => {
|
||||
visible.value = true
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
yhdhRef.value?.focus();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
const emit = defineEmits(["confirm"]);
|
||||
// 处理确定按钮点击
|
||||
const handleConfirm = async () => {
|
||||
if (!formRef.value) return;
|
||||
|
||||
// 表单验证
|
||||
const valid = await formRef.value.validate();
|
||||
if (valid) {
|
||||
checkYsUser({ ...formData.value, ...props.labPatKey }).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
emit('confirm', formData.value)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// 处理取消按钮点击
|
||||
const cancel = () => {
|
||||
formData.value = {
|
||||
yhdh: '',
|
||||
userName: '',
|
||||
mm: '',
|
||||
}
|
||||
formRef.value?.resetFields();
|
||||
visible.value = false
|
||||
};
|
||||
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
formData.value.userName = props.userList.find((item: any) => item.userName == value)?.nickName || value
|
||||
};
|
||||
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
cancel
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
311
src/components/vxeTable/index.vue
Normal file
@ -0,0 +1,311 @@
|
||||
<!--
|
||||
* vxe-table 通用表格组件 适用数据量大
|
||||
* @props columns: 表格列配置
|
||||
* @props tableData: 表格数据
|
||||
* @props loading: 加载状态
|
||||
* @props rowConfig: 行配置
|
||||
* @props showOverflow: 是否显示内容溢出省略
|
||||
* @props highlightCurrentRow: 是否高亮当前行
|
||||
* @props scrollYConfig: 纵向滚动配置
|
||||
* scroll-y 纵向滚动 设置虚拟滚动
|
||||
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="common-table-container">
|
||||
<vxe-table :data="tableData" :loading="loading" border :checkbox-config="config.checkboxConfig"
|
||||
:height="scrollYConfig.height" @checkbox-change="handleCheckboxChange" :row-config="rowConfig"
|
||||
:show-overflow="showOverflow" @current-change="handleRowClick" ref="tableRef" :size="size"
|
||||
:class="{ 'drag-table': enableRowDrag }" :current-row="currentRow" :scroll-y="scrollYConfig"
|
||||
:tooltip-config="{ appendToBody: true, zIndex: 3000 }"
|
||||
:header-cell-class-name="enableColumnDrag ? 'el-table-header-cell' : ''" v-bind="$attrs">
|
||||
<!-- 动态渲染列 -->
|
||||
<template v-for="(column, i) in columns" :key="`${column.field}-${i}`">
|
||||
<vxe-column type="checkbox" width="40" align="center" v-if="column.type == 'selection'" />
|
||||
<vxe-column width="40" align="center" :title="column.title || '序号'" v-if="column.type == 'seq'">
|
||||
<template #default="scope">
|
||||
{{ scope.row._index }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column v-bind="column" v-if="column.field">
|
||||
<!-- 自定义列模板 -->
|
||||
<template v-if="column.slotName" #default="scope">
|
||||
<slot :name="column.slotName" :row="scope.row" :$index="scope.$rowIndex"></slot>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</template>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, watch, onMounted } from 'vue'
|
||||
import Sortable from 'sortablejs'; // 引入sortablejs
|
||||
import type { VxeComponentSizeType, VxeColumnPropTypes } from 'vxe-table'
|
||||
|
||||
// 定义列配置类型
|
||||
interface TableColumn {
|
||||
field: string
|
||||
title: string
|
||||
width?: number | string
|
||||
align?: string,
|
||||
slotName?: string // 自定义插槽名称
|
||||
[key: string]: any // 支持其他vxe-column属性
|
||||
}
|
||||
|
||||
// 定义props类型
|
||||
const props = defineProps({
|
||||
// 表格数据
|
||||
tableData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 加载状态
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 列配置
|
||||
columns: {
|
||||
type: Array as () => TableColumn[],
|
||||
required: true
|
||||
},
|
||||
// 行配置
|
||||
rowConfig: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
isHover: true, height: 30, isCurrent: true, keyField: '_index'
|
||||
})
|
||||
},
|
||||
// 表格配置
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 是否显示内容溢出省略
|
||||
showOverflow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否高亮当前行 已废弃
|
||||
highlightCurrentRow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
// 纵向滚动配置
|
||||
scrollYConfig: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
enabled: true, // 强制启用虚拟滚动
|
||||
rSize: 30, // 行高(需与实际行高一致)
|
||||
height: 600, // 固定表格高度(关键,单位px)
|
||||
})
|
||||
},
|
||||
// 表格尺寸
|
||||
size: {
|
||||
type: String as () => VxeComponentSizeType,
|
||||
default: 'medium'
|
||||
},
|
||||
// 拖拽列
|
||||
enableColumnDrag: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 拖拽行
|
||||
enableRowDrag: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['current-change', "column-drag-end", "row-drag-end", "selection-change"])
|
||||
|
||||
const tableRef = ref<any>(null)
|
||||
const currentRow = ref<any>(null)
|
||||
// 处理行点击
|
||||
const handleRowClick = (params: { row: any, $rowIndex, column, $columnIndex, cell, $event }) => {
|
||||
currentRow.value = params.row
|
||||
emits('current-change', params.row, params.$rowIndex, params.column, params.$columnIndex, params.cell, params.$event)
|
||||
}
|
||||
|
||||
const handleCheckboxChange = ({ checked, records }: { checked: boolean, records: any[] }) => {
|
||||
// console.log('选中的数据:', records);
|
||||
// console.log('是否全选:', checked);
|
||||
emits('selection-change', records)
|
||||
};
|
||||
|
||||
// 处理行选择
|
||||
const toggleRowSelection = (row: any, checked: boolean) => {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.setCheckboxRow(row, checked)
|
||||
}
|
||||
}
|
||||
// 获取所有选中行数据
|
||||
const allSelection = () => {
|
||||
return tableRef.value.getCheckboxRecords()
|
||||
}
|
||||
|
||||
// 设置当前行
|
||||
const setCurrentRow = (row: any) => {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.setCurrentRow(row)
|
||||
nextTick(() => {
|
||||
tableRef.value.scrollToRow(row)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 清除高亮行
|
||||
const clearCurrentRow = () => {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.clearCurrentRow()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 初始化列拖拽功能
|
||||
onMounted(() => {
|
||||
if (props.enableColumnDrag && tableRef.value) {
|
||||
initColumnDrag();
|
||||
}
|
||||
|
||||
if (props.enableRowDrag && tableRef.value) {
|
||||
initRowDrag();
|
||||
}
|
||||
});
|
||||
|
||||
// 监听数据变化时重置当前行
|
||||
watch(() => props.tableData, (newVal) => {
|
||||
// 自定义索引
|
||||
if (newVal) {
|
||||
props.tableData.forEach((item: any, index) => {
|
||||
item._index = index + 1
|
||||
})
|
||||
}
|
||||
|
||||
currentRow.value = null
|
||||
})
|
||||
|
||||
// 初始化列拖拽
|
||||
const initColumnDrag = () => {
|
||||
// 获取表头单元格
|
||||
const tableHeader = tableRef.value.$el.querySelector('.vxe-table--header thead tr');
|
||||
if (!tableHeader) return;
|
||||
// 初始化拖拽
|
||||
const sortable = new Sortable(tableHeader, {
|
||||
animation: 150, // 动画时间
|
||||
handle: '.el-table-header-cell', // 拖拽手柄
|
||||
ghostClass: 'sortable-ghost', // 拖拽时的占位符样式
|
||||
onEnd: (evt: any) => {
|
||||
// console.log('evt==>', evt);
|
||||
// 过滤掉固定列
|
||||
const draggableColumns = props.columns.filter(col => !col.fixed);
|
||||
|
||||
// 如果发生了位置变化
|
||||
if (evt.oldIndex !== evt.newIndex && draggableColumns.length) {
|
||||
// 复制原数组并调整顺序
|
||||
const newColumns = [...draggableColumns];
|
||||
const [movedItem] = newColumns.splice(evt.oldIndex, 1);
|
||||
newColumns.splice(evt.newIndex, 0, movedItem);
|
||||
|
||||
// 更新原始columns数组中对应列的位置
|
||||
const updatedColumns = [...props.columns];
|
||||
// 先移除所有可拖拽列
|
||||
const nonDraggableColumns = updatedColumns.filter(col => col.fixed);
|
||||
// 合并固定列和新顺序的可拖拽列
|
||||
const resultColumns = nonDraggableColumns.concat(newColumns);
|
||||
|
||||
// 触发事件,通知父组件列顺序已改变
|
||||
emits('column-drag-end', {
|
||||
oldIndex: evt.oldIndex,
|
||||
newIndex: evt.newIndex,
|
||||
columns: [...resultColumns]
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化行拖拽
|
||||
const initRowDrag = () => {
|
||||
|
||||
const tableBody = tableRef.value.$el.querySelector('.vxe-table--body-wrapper tbody');
|
||||
const sortable = new Sortable(tableBody, {
|
||||
animation: 150, // 拖拽动画时长
|
||||
ghostClass: 'sortable-ghost', // 拖拽占位符样式
|
||||
chosenClass: 'sortable-chosen', // 选中行样式
|
||||
// 拖拽结束回调
|
||||
onEnd: (evt: any) => {
|
||||
const { oldIndex, newIndex } = evt
|
||||
if (oldIndex === newIndex) return // 未改变位置则不处理
|
||||
|
||||
// 调整数组顺序
|
||||
const moveRow = props.tableData.splice(oldIndex, 1)[0]
|
||||
props.tableData.splice(newIndex, 0, moveRow)
|
||||
|
||||
// 重新更新排序值
|
||||
props.tableData.forEach((item: any, index) => {
|
||||
item.sort = index + 1
|
||||
})
|
||||
// console.log("🚀 ~ initRowDrag ~ props.tableData:", props.tableData)
|
||||
emits('row-drag-end', {
|
||||
oldIndex,
|
||||
newIndex,
|
||||
list: props.tableData
|
||||
})
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 暴露公共方法
|
||||
defineExpose({
|
||||
setCurrentRow,
|
||||
clearCurrentRow,
|
||||
toggleRowSelection,
|
||||
allSelection,
|
||||
tableRef,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.common-table-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.vxe-header--row th) {
|
||||
border-color: #1F6DD3;
|
||||
background-color: #1F6DD3;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.vxe-body--row td) {
|
||||
border-color: #1F6DD3;
|
||||
}
|
||||
|
||||
:deep(.vxe-table--row-hover) {
|
||||
background-color: #1F6DD3;
|
||||
}
|
||||
|
||||
:deep(.vxe-table--current-row) {
|
||||
background-color: #1F6DD3;
|
||||
}
|
||||
|
||||
:deep(.el-table-header-cell) {
|
||||
cursor: move;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
// 表格边框
|
||||
:deep(.vxe-table--render-default.border--full .vxe-body--column) {
|
||||
background-image: linear-gradient(#96B8D9, #96B8D9), linear-gradient(#96B8D9, #96B8D9) !important;
|
||||
}
|
||||
|
||||
// 表头边框
|
||||
:deep(.vxe-table--render-default.border--full .vxe-header--column) {
|
||||
background-image: linear-gradient(#1F6DD3, #1F6DD3), linear-gradient(#1F6DD3, #1F6DD3) !important;
|
||||
}
|
||||
</style>
|
||||
16
src/env.d.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
[elemName: string]: HTMLAttributes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
1
src/hooks/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './lisData/dictData';
|
||||
65
src/hooks/lisData/dictData.ts
Normal file
@ -0,0 +1,65 @@
|
||||
//仪器,字典数据自动格式化类
|
||||
import { DictData } from "@/types/index";
|
||||
import { getGroupInstrdList } from "@/api/liswork/work/LisWork";
|
||||
import { comDict } from "@/utils/dict";
|
||||
|
||||
const dictData = ref<DictData>({});
|
||||
const instrOptions = ref<{ yq: string; yqmc: string }[]>([]);
|
||||
|
||||
export const getYqData = (data?: any) => {
|
||||
// 避免重复请求
|
||||
// if (instrOptions.value.length > 0) return;
|
||||
getGroupInstrdList(data).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
instrOptions.value = res.data.map((item: any) => ({
|
||||
yq: item.yq.trim(),
|
||||
yqmc: item.yqmc,
|
||||
}));
|
||||
}
|
||||
});
|
||||
};
|
||||
// 正在请求中的字典标记,防止并发重复调用
|
||||
const pendingDict = new Set<string>()
|
||||
|
||||
export const getDictData = async (...args: string[]) => {
|
||||
// 过滤:无缓存 且 当前没有正在请求
|
||||
const needReqKeys = args.filter(key => !(key in dictData.value) && !pendingDict.has(key))
|
||||
|
||||
if (needReqKeys.length === 0) return
|
||||
|
||||
// 标记开始请求
|
||||
needReqKeys.forEach(k => pendingDict.add(k))
|
||||
|
||||
try {
|
||||
const dictRefs = await comDict(...needReqKeys)
|
||||
needReqKeys.forEach((key) => {
|
||||
if (dictRefs[key] !== undefined) {
|
||||
dictData.value[key] = toRaw(dictRefs[key].value) || []
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
// 请求结束无论成功失败都清除标记
|
||||
needReqKeys.forEach(k => pendingDict.delete(k))
|
||||
}
|
||||
}
|
||||
|
||||
//字典数据格式化方法
|
||||
export const formatDict = (v: string, dictType: string) => {
|
||||
if (v == undefined) return;
|
||||
return (
|
||||
dictData.value[dictType]?.find((item: any) => item.value == v.trim())
|
||||
?.label || v
|
||||
);
|
||||
};
|
||||
|
||||
// 通用接口获取的字典数据赋值方法
|
||||
export const getOptionSelect = (dictType: string, list: any[]) => {
|
||||
dictData.value[dictType] = list || [];
|
||||
};
|
||||
|
||||
//仪器格式化方法
|
||||
export const formatInstr = (v: string) => {
|
||||
return instrOptions.value.find((item: any) => item.yq == v.trim())?.yqmc || v;
|
||||
};
|
||||
|
||||
export { dictData, instrOptions };
|
||||
53
src/hooks/messageBox.ts
Normal file
@ -0,0 +1,53 @@
|
||||
// 兼容verbatimModuleSyntax:拆分/标记类型与值导入
|
||||
import { ElMessageBox } from "element-plus";
|
||||
import type { ElMessageBoxOptions } from "element-plus";
|
||||
|
||||
/**
|
||||
* 极简删除确认框封装(支持返回值判断)
|
||||
* @param {string} [message] - 自定义删除提示信息(可选)
|
||||
* @param {Partial<MessageBoxConfirmOptions>} [customOptions] - 自定义配置(可选)
|
||||
* @returns {Promise<boolean>} 确认返回true,取消/关闭返回false
|
||||
*/
|
||||
export const deleteConfirm = (
|
||||
message?: string,
|
||||
customOptions?: Partial<ElMessageBoxOptions>
|
||||
) => {
|
||||
// 删除场景默认配置
|
||||
const defaultOptions: ElMessageBoxOptions = {
|
||||
title: "删除确认",
|
||||
message: message || "此操作将永久删除该数据,无法恢复,是否继续?",
|
||||
confirmButtonText: "确认删除",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
//center: true,
|
||||
};
|
||||
|
||||
// 合并默认配置与自定义配置
|
||||
const finalOptions = { ...defaultOptions, ...customOptions };
|
||||
|
||||
// 核心修改:无论确认/取消,都resolve布尔值,不触发reject
|
||||
return new Promise<boolean>((resolve) => {
|
||||
ElMessageBox.confirm(finalOptions.message, finalOptions.title, finalOptions)
|
||||
.then(() => resolve(true)) // 确认:返回true
|
||||
.catch(() => resolve(false)); // 取消/关闭:返回false(不再reject)
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 使用示例
|
||||
const handleDelete = async (id: number) => {
|
||||
// 直接获取返回值:true=确认,false=取消
|
||||
const isConfirmed = await deleteConfirm('是否删除数据?', { title: '自定义标题', type: 'warning' })
|
||||
|
||||
if (isConfirmed) {
|
||||
// 确认删除:执行业务逻辑
|
||||
// await api.deleteData(id) // 真实接口请求
|
||||
ElMessage.success(`ID为${id}的数据删除成功!`)
|
||||
console.log(`执行删除操作,数据ID:${id}`)
|
||||
} else {
|
||||
// 取消删除:给出提示(可选)
|
||||
ElMessage.info('已取消删除操作')
|
||||
console.log('用户取消删除')
|
||||
}
|
||||
}
|
||||
*/
|
||||
@ -3,7 +3,7 @@
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition name="fade-transform" mode="out-in">
|
||||
<keep-alive :include="tagsViewStore.cachedViews">
|
||||
<component v-if="!route.meta.link" :is="Component" :key="route.path"/>
|
||||
<component v-if="!route.meta.link" :is="Component" :key="route.path" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
@ -21,24 +21,24 @@ const tagsViewStore = useTagsViewStore()
|
||||
<style lang="scss" scoped>
|
||||
.app-main {
|
||||
/* 50= navbar 50 */
|
||||
min-height: calc(100vh - 50px);
|
||||
min-height: calc(100vh - 3.125rem);
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 50px;
|
||||
.fixed-header+.app-main {
|
||||
padding-top: 3.125rem;
|
||||
}
|
||||
|
||||
.hasTagsView {
|
||||
.app-main {
|
||||
/* 84 = navbar + tags-view = 50 + 34 */
|
||||
min-height: calc(100vh - 84px);
|
||||
min-height: calc(100vh - 5.25rem);
|
||||
}
|
||||
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 84px;
|
||||
.fixed-header+.app-main {
|
||||
padding-top: 5.25rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -65,4 +65,3 @@ const tagsViewStore = useTagsViewStore()
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@ -1,54 +1,66 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" />
|
||||
<top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" />
|
||||
<!-- 侧边栏折叠按钮(保留原有功能) -->
|
||||
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container"
|
||||
@toggleClick="toggleSideBar" />
|
||||
|
||||
<div class="right-menu">
|
||||
<template v-if="appStore.device !== 'mobile'">
|
||||
<header-search id="header-search" class="right-menu-item" />
|
||||
|
||||
<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||
</el-tooltip> -->
|
||||
|
||||
<!-- <el-tooltip content="文档地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||
</el-tooltip> -->
|
||||
<!-- 核心改造:替换面包屑/顶部导航,改为产品名称 + 登录信息布局 -->
|
||||
<div class="custom-header-content">
|
||||
<!-- 左侧:APP产品名称 -->
|
||||
<div class="app-name">
|
||||
{{ formatDict(userStore.sysLoginParam.loginYLJG || '1', 'HOS') }}
|
||||
</div>
|
||||
|
||||
<!-- 右侧:功能按钮 + 登录信息 + 原生设置菜单 -->
|
||||
<div class="right-content">
|
||||
<!-- 保留原有功能按钮(搜索、全屏、布局大小)
|
||||
<template v-if="appStore.device !== 'mobile'">
|
||||
<header-search id="header-search" class="right-menu-item" />
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
-->
|
||||
<!-- 登录人信息(姓名 + 角色) -->
|
||||
<div class="user-info" v-if="userStore.nickName">
|
||||
欢迎,{{ userStore.nickName }}({{ userStore.roleName }})
|
||||
</div>
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
|
||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<div class="avatar-container">
|
||||
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
|
||||
<div class="avatar-wrapper">
|
||||
<img :src="userStore.avatar" class="user-avatar" />
|
||||
<el-icon><caret-bottom /></el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<router-link to="/user/profile">
|
||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||
</router-link>
|
||||
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
|
||||
<span>布局设置</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided command="logout">
|
||||
<span>退出登录</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<!-- 原生个人信息/设置菜单(保留原有功能) -->
|
||||
<div class="avatar-container">
|
||||
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
|
||||
<div class="avatar-wrapper">
|
||||
<img :src="userStore.avatar" class="user-avatar" />
|
||||
<el-icon><caret-bottom /></el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<router-link to="/user/profile">
|
||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||
</router-link>
|
||||
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
|
||||
<span>布局设置</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="clearCache">
|
||||
<span>清除缓存</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided command="logout">
|
||||
<span>退出登录</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
// 引入原有组件
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import TopNav from '@/components/TopNav'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
@ -57,14 +69,35 @@ import SizeSelect from '@/components/SizeSelect'
|
||||
import HeaderSearch from '@/components/HeaderSearch'
|
||||
import RuoYiGit from '@/components/RuoYi/Git'
|
||||
import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||
// 引入Store
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
|
||||
// 引入图标和默认头像(可替换为你的默认头像)
|
||||
import { CaretBottom } from '@element-plus/icons-vue'
|
||||
import { formatDict, getDictData } from '@/hooks'
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
import { useRoute } from 'vue-router';
|
||||
const route = useRoute();
|
||||
// 处理角色名称(取第一个角色,多角色可自定义)
|
||||
const roleName = computed(() => {
|
||||
if (!userStore.roles || userStore.roles.length === 0) {
|
||||
return '普通用户'
|
||||
}
|
||||
// 角色编码映射表:key 是你的 roles 编码,value 是要显示的中文
|
||||
const roleMap = {
|
||||
'ROLE_DEFAULT': '普通用户',
|
||||
'admin': '管理员',
|
||||
'ROLE_ADMIN': '超级管理员',
|
||||
'ROLE_OPERATOR': '操作员' // 按你的实际角色编码添加
|
||||
}
|
||||
// 取第一个角色编码,映射为中文
|
||||
return roleMap[userStore.roles[0]] || userStore.roles[0]
|
||||
})
|
||||
|
||||
// 原有方法保留
|
||||
function toggleSideBar() {
|
||||
appStore.toggleSideBar()
|
||||
}
|
||||
@ -74,6 +107,9 @@ function handleCommand(command) {
|
||||
case "setLayout":
|
||||
setLayout();
|
||||
break;
|
||||
case "clearCache":
|
||||
clearCache();
|
||||
break;
|
||||
case "logout":
|
||||
logout();
|
||||
break;
|
||||
@ -82,6 +118,31 @@ function handleCommand(command) {
|
||||
}
|
||||
}
|
||||
|
||||
const clearCache = () => {
|
||||
console.log(route.path);
|
||||
const routeColumnKeyMap = {
|
||||
'/liswork/work': 'cgjyList_column_config', // 检验列表页面
|
||||
'/liswork/micro': 'wswList_column_config', // 微生物列表页面
|
||||
};
|
||||
|
||||
// 获取当前页面的缓存KEY
|
||||
const currentKey = routeColumnKeyMap[route.path];
|
||||
if (!currentKey) {
|
||||
ElMessage.warning('当前页面无表格列缓存可清除');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
localStorage.removeItem(currentKey);
|
||||
ElMessage.success('当前页面表格列缓存已清除');
|
||||
// 可选:刷新页面使配置生效(或通知对应页面重置列)
|
||||
location.reload();
|
||||
} catch (e) {
|
||||
console.error('清除当前列缓存失败', e);
|
||||
ElMessage.error('清除缓存失败');
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@ -91,27 +152,41 @@ function logout() {
|
||||
userStore.logOut().then(() => {
|
||||
location.href = '/index';
|
||||
})
|
||||
}).catch(() => { });
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
|
||||
const emits = defineEmits(['setLayout'])
|
||||
|
||||
function setLayout() {
|
||||
emits('setLayout');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDictData('HOS')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.navbar {
|
||||
height: 50px;
|
||||
height: 3.125rem;
|
||||
/* 固定高度,与原有一致 */
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||
//background: #fff;
|
||||
background: #304156;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.15);
|
||||
//box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||
display: flex;
|
||||
/* 改为flex布局,确保子元素对齐 */
|
||||
align-items: center;
|
||||
/* 垂直居中 */
|
||||
|
||||
.hamburger-container {
|
||||
line-height: 46px;
|
||||
line-height: 3.125rem;
|
||||
/* 与导航栏高度一致 */
|
||||
height: 100%;
|
||||
float: left;
|
||||
padding: 0 1rem;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
@ -121,71 +196,104 @@ function setLayout() {
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.topmenu-container {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
}
|
||||
|
||||
.errLog-container {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.right-menu {
|
||||
float: right;
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
/* 核心布局:产品名称 + 右侧内容容器 */
|
||||
.custom-header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
/* 占满剩余宽度 */
|
||||
padding: 0 1.25rem;
|
||||
height: 100%;
|
||||
margin-left: .3125rem;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
/* 产品名称样式 */
|
||||
.app-name {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
/* 若依主题色,可替换为品牌色 */
|
||||
white-space: nowrap;
|
||||
/* 防止换行 */
|
||||
font-style: italic;
|
||||
/* 关键:字体倾斜 */
|
||||
/* 可选优化:增加倾斜角度控制(默认 italic 约 14 度,可自定义) */
|
||||
/* transform: skewX(-10deg); /* 向左倾斜 10 度,正负值控制倾斜方向 */
|
||||
}
|
||||
|
||||
/* 右侧内容容器(功能按钮 + 用户信息 + 头像菜单) */
|
||||
.right-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .75rem;
|
||||
/* 元素间距,可调整 */
|
||||
white-space: nowrap;
|
||||
/* 防止换行 */
|
||||
}
|
||||
|
||||
/* 用户信息样式 */
|
||||
.user-info {
|
||||
font-size: .875rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #e6f7f4;
|
||||
}
|
||||
|
||||
/* 原有右侧菜单样式调整 */
|
||||
.right-menu-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 .5rem;
|
||||
height: 100%;
|
||||
font-size: 1.125rem;
|
||||
color: #5a5e66;
|
||||
vertical-align: text-bottom;
|
||||
|
||||
&.hover-effect {
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-menu-item {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
font-size: 18px;
|
||||
color: #5a5e66;
|
||||
vertical-align: text-bottom;
|
||||
/* 头像容器样式调整 */
|
||||
.avatar-container {
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .25rem;
|
||||
/* 头像与下拉图标间距 */
|
||||
|
||||
&.hover-effect {
|
||||
.user-avatar {
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
width: 2.25rem;
|
||||
/* 调整头像大小 */
|
||||
height: 2.25rem;
|
||||
border-radius: 50%;
|
||||
/* 圆形头像,可改为10px保持原有风格 */
|
||||
object-fit: cover;
|
||||
/* 防止头像变形 */
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
}
|
||||
i {
|
||||
cursor: pointer;
|
||||
font-size: .75rem;
|
||||
color: #5a5e66;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
margin-right: 40px;
|
||||
|
||||
.avatar-wrapper {
|
||||
margin-top: 5px;
|
||||
position: relative;
|
||||
|
||||
.user-avatar {
|
||||
cursor: pointer;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
i {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 25px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 隐藏原有面包屑和顶部导航(已替换) */
|
||||
.breadcrumb-container,
|
||||
.topmenu-container {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
191
src/layout/components/Navbarold.vue
Normal file
@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" />
|
||||
<top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" />
|
||||
|
||||
<div class="right-menu">
|
||||
<template v-if="appStore.device !== 'mobile'">
|
||||
<header-search id="header-search" class="right-menu-item" />
|
||||
|
||||
<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||
</el-tooltip> -->
|
||||
|
||||
<!-- <el-tooltip content="文档地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||
</el-tooltip> -->
|
||||
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
|
||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<div class="avatar-container">
|
||||
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
|
||||
<div class="avatar-wrapper">
|
||||
<img :src="userStore.avatar" class="user-avatar" />
|
||||
<el-icon><caret-bottom /></el-icon>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<router-link to="/user/profile">
|
||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||
</router-link>
|
||||
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
|
||||
<span>布局设置</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided command="logout">
|
||||
<span>退出登录</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import TopNav from '@/components/TopNav'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
import Screenfull from '@/components/Screenfull'
|
||||
import SizeSelect from '@/components/SizeSelect'
|
||||
import HeaderSearch from '@/components/HeaderSearch'
|
||||
import RuoYiGit from '@/components/RuoYi/Git'
|
||||
import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
function toggleSideBar() {
|
||||
appStore.toggleSideBar()
|
||||
}
|
||||
|
||||
function handleCommand(command) {
|
||||
switch (command) {
|
||||
case "setLayout":
|
||||
setLayout();
|
||||
break;
|
||||
case "logout":
|
||||
logout();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
userStore.logOut().then(() => {
|
||||
location.href = '/index';
|
||||
})
|
||||
}).catch(() => { });
|
||||
}
|
||||
|
||||
const emits = defineEmits(['setLayout'])
|
||||
function setLayout() {
|
||||
emits('setLayout');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.navbar {
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||
|
||||
.hamburger-container {
|
||||
line-height: 46px;
|
||||
height: 100%;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.topmenu-container {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
}
|
||||
|
||||
.errLog-container {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.right-menu {
|
||||
float: right;
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
display: flex;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.right-menu-item {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
font-size: 18px;
|
||||
color: #5a5e66;
|
||||
vertical-align: text-bottom;
|
||||
|
||||
&.hover-effect {
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
margin-right: 40px;
|
||||
|
||||
.avatar-wrapper {
|
||||
margin-top: 5px;
|
||||
position: relative;
|
||||
|
||||
.user-avatar {
|
||||
cursor: pointer;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
i {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 25px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -8,8 +8,10 @@
|
||||
<img src="@/assets/images/dark.svg" alt="dark" />
|
||||
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
|
||||
<i aria-label="图标: check" class="anticon anticon-check">
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class>
|
||||
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" />
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
|
||||
focusable="false" class>
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" />
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
@ -18,8 +20,10 @@
|
||||
<img src="@/assets/images/light.svg" alt="light" />
|
||||
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
|
||||
<i aria-label="图标: check" class="anticon anticon-check">
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class>
|
||||
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" />
|
||||
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
|
||||
focusable="false" class>
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z" />
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
@ -28,7 +32,7 @@
|
||||
<div class="drawer-item">
|
||||
<span>主题颜色</span>
|
||||
<span class="comp-style">
|
||||
<el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange"/>
|
||||
<el-color-picker v-model="theme" :predefine="predefineColors" @change="themeChange" />
|
||||
</span>
|
||||
</div>
|
||||
<el-divider />
|
||||
@ -92,7 +96,7 @@ const showSettings = ref(false);
|
||||
const theme = ref(settingsStore.theme);
|
||||
const sideTheme = ref(settingsStore.sideTheme);
|
||||
const storeSettings = computed(() => settingsStore);
|
||||
const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]);
|
||||
const predefineColors = ref(["#1F6DD3", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]);
|
||||
|
||||
/** 是否需要topnav */
|
||||
function topNavChange(val) {
|
||||
@ -144,10 +148,12 @@ defineExpose({
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
line-height: 22px;
|
||||
font-weight: bold;
|
||||
|
||||
.drawer-title {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-drawer-block-checbox {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
@ -1,17 +1,10 @@
|
||||
<template>
|
||||
<div id="tags-view-container" class="tags-view-container">
|
||||
<scroll-pane ref="scrollPaneRef" class="tags-view-wrapper" @scroll="handleScroll">
|
||||
<router-link
|
||||
v-for="tag in visitedViews"
|
||||
:key="tag.path"
|
||||
:data-path="tag.path"
|
||||
:class="isActive(tag) ? 'active' : ''"
|
||||
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
||||
class="tags-view-item"
|
||||
:style="activeStyle(tag)"
|
||||
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
|
||||
@contextmenu.prevent="openMenu(tag, $event)"
|
||||
>
|
||||
<router-link v-for="tag in visitedViews" :key="tag.path" :data-path="tag.path"
|
||||
:class="isActive(tag) ? 'active' : ''" :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
||||
class="tags-view-item" :style="activeStyle(tag)" @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
|
||||
@contextmenu.prevent="openMenu(tag, $event)">
|
||||
{{ tag.title }}
|
||||
<span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
|
||||
<close class="el-icon-close" style="width: 1em; height: 1em;vertical-align: middle;" />
|
||||
@ -133,7 +126,7 @@ function initTags() {
|
||||
for (const tag of res) {
|
||||
// Must have tag name
|
||||
if (tag.name) {
|
||||
useTagsViewStore().addVisitedView(tag)
|
||||
useTagsViewStore().addVisitedView(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -243,66 +236,122 @@ function handleScroll() {
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.tags-view-container {
|
||||
height: 34px;
|
||||
height: 2.125rem;
|
||||
/* 稍微增加高度,让立体效果更明显 */
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #d8dce5;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
|
||||
background: #f5f7fa;
|
||||
/* 标签栏整体背景(浅灰,与标签区分) */
|
||||
/* 1. 去掉底部边框(关键:消除物理边框导致的缝隙) */
|
||||
border-bottom: none;
|
||||
/* 2. 弱化或去掉标签栏的底部阴影(避免阴影造成视觉缝隙) */
|
||||
box-shadow: 0 .0625rem .125rem rgba(0, 0, 0, 0.02);
|
||||
/* 仅保留极浅的顶部阴影 */
|
||||
/* 标签栏底部加一条浅线,区分标签栏和下方页面 */
|
||||
border-bottom: .0625rem solid #e0e0e0;
|
||||
|
||||
.tags-view-wrapper {
|
||||
.tags-view-item {
|
||||
/* 未激活标签:灰色渐变+立体阴影 */
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
border: 1px solid #d8dce5;
|
||||
color: #495060;
|
||||
background: #fff;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
margin-left: 5px;
|
||||
margin-top: 4px;
|
||||
&:first-of-type {
|
||||
margin-left: 15px;
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-right: 15px;
|
||||
height: 1.75rem;
|
||||
line-height: 1.75rem;
|
||||
padding: 0 .75rem;
|
||||
font-size: .75rem;
|
||||
margin-left: .25rem;
|
||||
margin-top: .25rem;
|
||||
border-radius: .25rem .25rem 0 0;
|
||||
/* 底部圆角去掉,与下方无缝感 */
|
||||
border: 1px solid #d0d0d0;
|
||||
/* 浅灰边框 */
|
||||
border-bottom-color: transparent;
|
||||
/* 底部边框透明,避免与标签栏线重叠 */
|
||||
|
||||
/* 灰色渐变:从上到下浅灰→深灰(模拟轻微凸起) */
|
||||
background: linear-gradient(180deg, #f0f0f0 0%, #e0e0e0 100%);
|
||||
|
||||
/* 立体阴影:底部轻微阴影+顶部内高光 */
|
||||
box-shadow:
|
||||
0 2px 4px rgba(0, 0, 0, 0.1),
|
||||
/* 底部阴影加深,突出悬浮感 */
|
||||
inset 0 1px 1px rgba(255, 255, 255, 0.8);
|
||||
/* 顶部内高光,增强凸起感 */
|
||||
|
||||
|
||||
color: #777;
|
||||
/* 文字灰色,不抢眼 */
|
||||
transition: all 0.2s ease;
|
||||
/* 过渡动画 */
|
||||
|
||||
/* 鼠标悬停时增强效果(未激活状态) */
|
||||
&:hover:not(.active) {
|
||||
background: linear-gradient(180deg, #f5f5f5 0%, #e8e8e8 100%);
|
||||
box-shadow:
|
||||
0 3px 4px rgba(0, 0, 0, 0.08),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||
border-color: #d0d0d0;
|
||||
color: #333;
|
||||
/* hover时文字略深 */
|
||||
}
|
||||
|
||||
/* 激活标签样式:深色渐变+强阴影,突出当前页 */
|
||||
&.active {
|
||||
background-color: #42b983;
|
||||
color: #fff;
|
||||
border-color: #42b983;
|
||||
/* 激活标签:从左到右的主题色渐变(示例用蓝紫色) */
|
||||
background: linear-gradient(90deg, #409eff 0%, #6b7aff 100%);
|
||||
color: #ffffff;
|
||||
/* 文字白色,与渐变背景对比 */
|
||||
border-color: #409eff;
|
||||
/* 边框与渐变颜色匹配 */
|
||||
box-shadow: 0 3px 6px rgba(64, 158, 255, 0.25),
|
||||
/* 外阴影(带颜色倾向,增强立体感) */
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
/* 内阴影(顶部亮边,模拟高光) */
|
||||
transform: translateY(-1px);
|
||||
/* 轻微上浮,与其他标签区分 */
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
background: #fff;
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
margin-right: 5px;
|
||||
margin-right: .3125rem;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
/* 小圆圈阴影,增强立体 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 右键菜单也增加立体效果 */
|
||||
.contextmenu {
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f9fafb 100%);
|
||||
z-index: 3000;
|
||||
position: absolute;
|
||||
list-style-type: none;
|
||||
padding: 5px 0;
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15),
|
||||
/* 外阴影 */
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||
/* 内阴影 */
|
||||
border: 1px solid #e5e7eb;
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 7px 16px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: #eee;
|
||||
background: #f0f5ff;
|
||||
/* hover 时浅蓝色背景,与整体风格呼应 */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -314,23 +363,25 @@ function handleScroll() {
|
||||
.tags-view-wrapper {
|
||||
.tags-view-item {
|
||||
.el-icon-close {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: 2px;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
vertical-align: .125rem;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transform-origin: 100% 50%;
|
||||
|
||||
&:before {
|
||||
transform: scale(0.6);
|
||||
display: inline-block;
|
||||
vertical-align: -3px;
|
||||
vertical-align: -0.1875rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #b4bccc;
|
||||
color: #fff;
|
||||
width: 12px !important;
|
||||
height: 12px !important;
|
||||
width: .75rem !important;
|
||||
height: .75rem !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
|
||||
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
||||
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
|
||||
<sidebar v-if="!sidebar.hide" class="sidebar-container" />
|
||||
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
|
||||
<div :class="{ 'fixed-header': fixedHeader }">
|
||||
@ -21,7 +21,10 @@ import defaultSettings from '@/settings'
|
||||
|
||||
import useAppStore from '@/store/modules/app'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import { initWebSocket } from '@/utils/webSocket'
|
||||
import { useCommonStore } from '@/store/modules/commonStore'
|
||||
|
||||
const mbStore = useCommonStore();
|
||||
const settingsStore = useSettingsStore()
|
||||
const theme = computed(() => settingsStore.theme);
|
||||
const sideTheme = computed(() => settingsStore.sideTheme);
|
||||
@ -60,11 +63,17 @@ const settingRef = ref(null);
|
||||
function setLayout() {
|
||||
settingRef.value.openSetting();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始化socket
|
||||
const url = `ws://47.97.125.165:8904/ws/msgserver/${mbStore.fingerprint}`
|
||||
initWebSocket({ fullUrl: url })
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/styles/mixin.scss";
|
||||
@import "@/assets/styles/variables.module.scss";
|
||||
@import "@/assets/styles/mixin.scss";
|
||||
@import "@/assets/styles/variables.module.scss";
|
||||
|
||||
.app-wrapper {
|
||||
@include clearfix;
|
||||
|
||||
57
src/main.js
@ -1,17 +1,28 @@
|
||||
import { createApp } from 'vue'
|
||||
import {
|
||||
createApp
|
||||
} from 'vue'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
import locale from 'element-plus/es/locale/lang/zh-cn'
|
||||
|
||||
import VxeUI from 'vxe-pc-ui'
|
||||
import 'vxe-pc-ui/lib/style.css'
|
||||
import VXETable from 'vxe-table'
|
||||
import 'vxe-table/lib/style.css'
|
||||
import '@/assets/styles/index.scss' // global css
|
||||
import '@/utils/polyfills';
|
||||
|
||||
import {
|
||||
setupRem
|
||||
} from './utils/rem';
|
||||
setupRem(); // 初始化rem适配
|
||||
// 先导入 jQuery 并设置全局变量
|
||||
|
||||
import * as $ from 'jquery';
|
||||
window.jQuery = $;
|
||||
window.$ = $;
|
||||
// import * as $ from 'jquery';
|
||||
// window.jQuery = $;
|
||||
// window.$ = $;
|
||||
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
@ -20,7 +31,9 @@ import directive from './directive' // directive
|
||||
|
||||
// 注册指令
|
||||
import plugins from './plugins' // plugins
|
||||
import { download } from '@/utils/request'
|
||||
import {
|
||||
download
|
||||
} from '@/utils/request'
|
||||
|
||||
// svg图标
|
||||
import 'virtual:svg-icons-register'
|
||||
@ -29,8 +42,18 @@ import elementIcons from '@/components/SvgIcon/svgicon'
|
||||
|
||||
import './permission' // permission control
|
||||
|
||||
import {useDict, comDict} from '@/utils/dict'
|
||||
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
|
||||
import {
|
||||
useDict,
|
||||
comDict
|
||||
} from '@/utils/dict'
|
||||
import {
|
||||
parseTime,
|
||||
resetForm,
|
||||
addDateRange,
|
||||
handleTree,
|
||||
selectDictLabel,
|
||||
selectDictLabels
|
||||
} from '@/utils/ruoyi'
|
||||
|
||||
// 分页组件
|
||||
import Pagination from '@/components/Pagination'
|
||||
@ -48,7 +71,14 @@ import ImagePreview from "@/components/ImagePreview"
|
||||
import TreeSelect from '@/components/TreeSelect'
|
||||
// 字典标签组件
|
||||
import DictTag from '@/components/DictTag'
|
||||
import Print from 'vue3-print-nb';
|
||||
// elTable表格组件
|
||||
import CustomTable from '@/components/elTable'
|
||||
// vxeTable 组件
|
||||
import CustomVxeTable from '@/components/vxeTable'
|
||||
// 下拉框表格组件
|
||||
import SelectTable from '@/components/SelectTable'
|
||||
import print from 'vue3-print-nb';
|
||||
import Vue3SeamlessScroll from 'vue3-seamless-scroll' // 引入插件
|
||||
const app = createApp(App)
|
||||
|
||||
// 全局方法挂载
|
||||
@ -71,10 +101,14 @@ app.component('ImageUpload', ImageUpload)
|
||||
app.component('ImagePreview', ImagePreview)
|
||||
app.component('RightToolbar', RightToolbar)
|
||||
app.component('Editor', Editor)
|
||||
app.component('CustomTable', CustomTable)
|
||||
app.component('CustomVxeTable', CustomVxeTable)
|
||||
app.component('SelectTable', SelectTable)
|
||||
|
||||
//VUE3标准方法注入全局方法
|
||||
app.provide('comDict', comDict);
|
||||
app.use(Print); // 注册打印插件
|
||||
app.use(print); // 注册打印插件
|
||||
app.use(Vue3SeamlessScroll)
|
||||
app.provide('$vuePrint', app.config.globalProperties.$vuePrint);
|
||||
app.use(router)
|
||||
app.use(store)
|
||||
@ -82,7 +116,8 @@ app.use(plugins)
|
||||
app.use(elementIcons)
|
||||
app.component('svg-icon', SvgIcon)
|
||||
directive(app)
|
||||
|
||||
app.use(VxeUI)
|
||||
app.use(VXETable)
|
||||
// 使用element-plus 并且设置全局的大小
|
||||
app.use(ElementPlus, {
|
||||
locale: locale,
|
||||
|
||||