数据大屏初始化
@ -5,6 +5,7 @@ VITE_APP_TITLE = '数字农业产业管理平台'
|
||||
VITE_APP_SUB_OS = '//localhost:9526/sub-operation-service/'
|
||||
VITE_APP_SUB_ADMIN = '//localhost:9527/sub-admin/'
|
||||
VITE_APP_SUB_GAS = '//localhost:9528/sub-government-affairs-service/'
|
||||
VITE_APP_SUB_GSS = '//localhost:9529/sub-government-screen-service/'
|
||||
# 接口
|
||||
VITE_APP_BASE_API = '/apis'
|
||||
VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
|
||||
|
86
main/src/components/custom-echart-bar-line/index.vue
Normal file
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div ref="chartRef" :style="{ height, width }"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, reactive, watchEffect } from 'vue';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { useEcharts } from '../../hooks/useEcharts';
|
||||
|
||||
export default {
|
||||
name: 'CustomEchartBarLine',
|
||||
props: {
|
||||
chartData: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
option: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'calc(100vh - 78px)',
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const chartRef = ref(null);
|
||||
const { setOptions } = useEcharts(chartRef);
|
||||
const option = reactive({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
label: {
|
||||
show: true,
|
||||
backgroundColor: '#333',
|
||||
},
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: [],
|
||||
},
|
||||
yAxis: [],
|
||||
series: [
|
||||
{
|
||||
name: 'bar',
|
||||
type: 'bar',
|
||||
data: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
props.chartData && initCharts();
|
||||
});
|
||||
|
||||
function initCharts() {
|
||||
if (props.option) {
|
||||
Object.assign(option, cloneDeep(props.option));
|
||||
}
|
||||
let typeArr = Array.from(new Set(props.chartData.map((item) => item.type)));
|
||||
let xAxisData = Array.from(new Set(props.chartData.map((item) => item.name)));
|
||||
let seriesData = [];
|
||||
typeArr.forEach((type, index) => {
|
||||
let obj = { name: type };
|
||||
let chartArr = props.chartData.filter((item) => type === item.type);
|
||||
obj['data'] = chartArr.map((item) => item.value);
|
||||
obj['type'] = chartArr[0].seriesType;
|
||||
obj['barWidth'] = chartArr[0].barWidth;
|
||||
obj['itemStyle'] = chartArr[0].itemStyle;
|
||||
seriesData.push(obj);
|
||||
});
|
||||
option.series = seriesData;
|
||||
option.xAxis.data = xAxisData;
|
||||
option.yAxis = props.option.yAxis;
|
||||
setOptions(option);
|
||||
}
|
||||
return { chartRef };
|
||||
},
|
||||
};
|
||||
</script>
|
@ -7,6 +7,7 @@ import CustomEchartBar from './custom-echart-bar';
|
||||
import CustomEchartPie from './custom-echart-pie';
|
||||
import CustomEchartLine from './custom-echart-line';
|
||||
import CustomEchartMixin from './custom-echart-mixin';
|
||||
import CustomEchartBarLine from './custom-echart-bar-line';
|
||||
|
||||
export {
|
||||
SvgIcon,
|
||||
@ -18,4 +19,5 @@ export {
|
||||
CustomEchartPie,
|
||||
CustomEchartLine,
|
||||
CustomEchartMixin,
|
||||
CustomEchartBarLine,
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import actions from './actions';
|
||||
|
||||
const { VITE_APP_SUB_OS, VITE_APP_SUB_ADMIN, VITE_APP_SUB_GAS } = import.meta.env;
|
||||
const { VITE_APP_SUB_OS, VITE_APP_SUB_ADMIN, VITE_APP_SUB_GAS, VITE_APP_SUB_GSS } = import.meta.env;
|
||||
|
||||
export const leftApps = [
|
||||
{
|
||||
@ -56,9 +56,9 @@ export const rightApps = [
|
||||
icon: 'images/platform/icon-app.png',
|
||||
},
|
||||
{
|
||||
name: 'sub-government-screen',
|
||||
entry: VITE_APP_SUB_ADMIN,
|
||||
activeRule: '/sub-government-screen/',
|
||||
name: 'sub-government-screen-service',
|
||||
entry: VITE_APP_SUB_GSS,
|
||||
activeRule: '/sub-government-screen-service/',
|
||||
title: '数据大屏',
|
||||
icon: 'images/platform/icon-screen.png',
|
||||
},
|
||||
@ -72,6 +72,13 @@ export const defaultApps = [
|
||||
title: '政务服务',
|
||||
icon: 'images/platform/icon-home.png',
|
||||
},
|
||||
{
|
||||
name: 'sub-government-screen-service',
|
||||
entry: VITE_APP_SUB_GSS,
|
||||
activeRule: '/sub-government-screen-service/',
|
||||
title: '数据大屏',
|
||||
icon: 'images/platform/icon-screen.png',
|
||||
},
|
||||
];
|
||||
|
||||
// export const microApps = [...defaultApps, ...leftApps, ...rightApps];
|
||||
|
@ -8,16 +8,19 @@
|
||||
"install:main": "cd main && yarn install",
|
||||
"install:sub-admin": "cd sub-admin && yarn install",
|
||||
"install:sub-gas": "cd sub-government-affairs-service && yarn install",
|
||||
"install:sub-gss": "cd sub-government-screen-service && yarn install",
|
||||
"install:sub-os": "cd sub-operation-service && yarn install",
|
||||
"dev": "npm-run-all --parallel dev:*",
|
||||
"dev:main": "cd main && yarn dev",
|
||||
"dev:sub-admin": "cd sub-app && yarn dev",
|
||||
"dev:sub-gas": "cd sub-government-affairs-service && yarn dev",
|
||||
"dev:sub-gss": "cd sub-government-screen-service && yarn dev",
|
||||
"dev:sub-os": "cd sub-operation-service && yarn dev",
|
||||
"build": "npm-run-all --serial build:*",
|
||||
"build:main": "cd main && yarn build",
|
||||
"build:sub-admin": "cd sub-admin && yarn build",
|
||||
"build:sub-gas": "cd sub-government-affairs-service && yarn build",
|
||||
"build:sub-gss": "cd sub-government-screen-service && yarn build",
|
||||
"build:sub-os": "cd sub-operation-service && yarn build",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
|
9
sub-government-screen-service/.editorconfig
Normal file
@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*.{js,jsx,ts,tsx,vue}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
end_of_line = auto
|
10
sub-government-screen-service/.env.development
Normal file
@ -0,0 +1,10 @@
|
||||
# 开发环境
|
||||
VITE_PORT = 9529
|
||||
VITE_MODE = 'DEV'
|
||||
VITE_APP_MIAN = 'daimp-front-main'
|
||||
VITE_APP_MIAN_URL = 'http://localhost:9000'
|
||||
VITE_APP_NAME = 'sub-government-screen-service'
|
||||
VITE_APP_BASE_API = '/apis'
|
||||
VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
|
||||
VITE_APP_UPLOAD_API = '/uploadApis'
|
||||
VITE_APP_UPLOAD_URL = 'http://192.168.18.99:9300'
|
10
sub-government-screen-service/.env.production
Normal file
@ -0,0 +1,10 @@
|
||||
# 生产环境
|
||||
VITE_MODE = 'PRO'
|
||||
VITE_APP_MIAN = 'daimp-front-main'
|
||||
VITE_APP_MIAN_URL = 'http://192.168.18.99:88'
|
||||
VITE_APP_NAME = 'sub-government-screen-service'
|
||||
# 接口
|
||||
VITE_APP_BASE_API = '/apis'
|
||||
VITE_APP_BASE_URL = ''
|
||||
VITE_APP_UPLOAD_API = '/uploadApis'
|
||||
VITE_APP_UPLOAD_URL = ''
|
14
sub-government-screen-service/.eslintignore
Normal file
@ -0,0 +1,14 @@
|
||||
*.sh
|
||||
*.md
|
||||
*.woff
|
||||
*.ttf
|
||||
.vscode
|
||||
.idea
|
||||
.husky
|
||||
.local
|
||||
dist
|
||||
src/assets
|
||||
node_modules
|
||||
Dockerfile
|
||||
stats.html
|
||||
tailwind.config.js
|
62
sub-government-screen-service/.eslintrc.cjs
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Descripttion: .eslintrc.cjs
|
||||
* 在VSCode中安装ESLint插件,编写过程中检测代码质量
|
||||
* ESLint 代码质量校验相关配置
|
||||
* 这里使用prettier作为代码格式化工具,用ESLint做代码质检
|
||||
* 相关配置使用下面extends扩展先做默认设置
|
||||
* 在.prettierrc.cjs文件中配置好后,格式化规则会以.prettierrc.cjs作为最终格式,所以不建议在本文件中做代码格式化相关配置
|
||||
* 相关prettier配置ESLint会默认加载为代码质检 格式化以prettier为主
|
||||
* 在本配置文件中只做代码质量约束规范配置
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2022-09-22 15:53:58
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-03-22 10:19:39
|
||||
*/
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
'eslint-config-prettier',
|
||||
'eslint:recommended',
|
||||
// 'plugin:@typescript-eslint/recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:vue/vue3-essential',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
files: ['.eslintrc.{js,cjs}'],
|
||||
parserOptions: {
|
||||
sourceType: 'script',
|
||||
},
|
||||
},
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
requireConfigFile: false,
|
||||
parser: '@babel/eslint-parser',
|
||||
// parser: '@typescript-eslint/parser',
|
||||
},
|
||||
plugins: ['vue', 'prettier'],
|
||||
globals: {
|
||||
defineProps: 'readonly',
|
||||
defineEmits: 'readonly',
|
||||
defineExpose: 'readonly',
|
||||
withDefaults: 'readonly',
|
||||
},
|
||||
// 这里时配置规则的,自己看情况配置
|
||||
rules: {
|
||||
'prettier/prettier': 'error',
|
||||
'no-debugger': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'vue/no-unused-vars': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
},
|
||||
};
|
116
sub-government-screen-service/.gitignore
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
20
sub-government-screen-service/.prettierignore
Normal file
@ -0,0 +1,20 @@
|
||||
## OS
|
||||
.DS_Store
|
||||
node_modules
|
||||
.idea
|
||||
.editorconfig
|
||||
package-lock.json
|
||||
.npmrc
|
||||
|
||||
# Ignored suffix
|
||||
*.log
|
||||
*.md
|
||||
*.svg
|
||||
*.png
|
||||
*ignore
|
||||
|
||||
## Local
|
||||
|
||||
## Built-files
|
||||
.cache
|
||||
dist
|
52
sub-government-screen-service/.prettierrc.cjs
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* @Descripttion: .prettierrc.cjs
|
||||
* 在VSCode中安装prettier插件 打开插件配置填写`.prettierrc.js` 将本文件作为其代码格式化规范
|
||||
* 在本文件中修改格式化规则,不会同时触发改变ESLint代码检查,所以每次修改本文件需要重启VSCode,ESLint检查才能同步代码格式化
|
||||
* 需要相应的代码格式化规范请自行查阅配置,下面为默认项目配置
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2022-09-22 15:53:58
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-24 19:22:25
|
||||
*/
|
||||
module.exports = {
|
||||
// 一行最多多少个字符
|
||||
printWidth: 150,
|
||||
// 指定每个缩进级别的空格数
|
||||
tabWidth: 2,
|
||||
// 使用制表符而不是空格缩进行
|
||||
useTabs: false,
|
||||
// 在语句末尾是否需要分号
|
||||
semi: true,
|
||||
// 是否使用单引号
|
||||
singleQuote: true,
|
||||
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
|
||||
quoteProps: 'as-needed',
|
||||
// 在JSX中使用单引号而不是双引号
|
||||
jsxSingleQuote: false,
|
||||
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
|
||||
trailingComma: 'es5',
|
||||
// 在对象文字中的括号之间打印空格
|
||||
bracketSpacing: true,
|
||||
// jsx 标签的反尖括号需要换行
|
||||
jsxBracketSameLine: false,
|
||||
// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
|
||||
arrowParens: 'always',
|
||||
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
// 指定要使用的解析器,不需要写文件开头的 @prettier
|
||||
requirePragma: false,
|
||||
// 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false,
|
||||
// 使用默认的折行标准 always\never\preserve
|
||||
proseWrap: 'preserve',
|
||||
// 指定HTML文件的全局空格敏感度 css\strict\ignore
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
// Vue文件脚本和样式标签缩进
|
||||
vueIndentScriptAndStyle: false,
|
||||
//在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
|
||||
//然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
|
||||
//对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
|
||||
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
|
||||
endOfLine: 'auto',
|
||||
};
|
17
sub-government-screen-service/.stylelintignore
Normal file
@ -0,0 +1,17 @@
|
||||
# .stylelintignore
|
||||
# 旧的不需打包的样式库
|
||||
*.min.css
|
||||
|
||||
# 其他类型文件
|
||||
*.js
|
||||
*.jpg
|
||||
*.png
|
||||
*.eot
|
||||
*.ttf
|
||||
*.woff
|
||||
*.json
|
||||
|
||||
# 测试和打包目录
|
||||
/dist/*
|
||||
/node_modules/*
|
||||
/src/assets/*
|
131
sub-government-screen-service/.stylelintrc.cjs
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* @Descripttion: .stylelintrc.cjs
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2022-09-22 15:53:58
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-24 18:49:26
|
||||
*/
|
||||
module.exports = {
|
||||
root: true,
|
||||
plugins: ['stylelint-order', 'stylelint-scss'],
|
||||
extends: [
|
||||
'stylelint-config-standard',
|
||||
'stylelint-config-standard-scss',
|
||||
'stylelint-config-prettier',
|
||||
'stylelint-config-html/vue',
|
||||
'stylelint-config-recommended-vue',
|
||||
'stylelint-config-recommended-scss'
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.{html,vue}'],
|
||||
customSyntax: 'postcss-html'
|
||||
}
|
||||
],
|
||||
rules: {
|
||||
indentation: 2,
|
||||
'selector-pseudo-element-no-unknown': [
|
||||
true,
|
||||
{
|
||||
ignorePseudoElements: ['v-deep', ':deep']
|
||||
}
|
||||
],
|
||||
'number-leading-zero': 'always',
|
||||
'no-descending-specificity': null,
|
||||
'function-url-quotes': 'always',
|
||||
'string-quotes': 'single',
|
||||
'unit-case': null,
|
||||
'color-hex-case': 'lower',
|
||||
'color-hex-length': 'long',
|
||||
'rule-empty-line-before': 'never',
|
||||
'font-family-no-missing-generic-family-keyword': null,
|
||||
'selector-type-no-unknown': null,
|
||||
'block-opening-brace-space-before': 'always',
|
||||
'at-rule-no-unknown': null,
|
||||
'no-duplicate-selectors': null,
|
||||
'property-no-unknown': null,
|
||||
'no-empty-source': null,
|
||||
'selector-class-pattern': null,
|
||||
'keyframes-name-pattern': null,
|
||||
'selector-pseudo-class-no-unknown': [true, { ignorePseudoClasses: ['global', 'deep'] }],
|
||||
'function-no-unknown': null,
|
||||
'order/properties-order': [
|
||||
'position',
|
||||
'top',
|
||||
'right',
|
||||
'bottom',
|
||||
'left',
|
||||
'z-index',
|
||||
'display',
|
||||
'justify-content',
|
||||
'align-items',
|
||||
'float',
|
||||
'clear',
|
||||
'overflow',
|
||||
'overflow-x',
|
||||
'overflow-y',
|
||||
'margin',
|
||||
'margin-top',
|
||||
'margin-right',
|
||||
'margin-bottom',
|
||||
'margin-left',
|
||||
'padding',
|
||||
'padding-top',
|
||||
'padding-right',
|
||||
'padding-bottom',
|
||||
'padding-left',
|
||||
'width',
|
||||
'min-width',
|
||||
'max-width',
|
||||
'height',
|
||||
'min-height',
|
||||
'max-height',
|
||||
'font-size',
|
||||
'font-family',
|
||||
'font-weight',
|
||||
'border',
|
||||
'border-style',
|
||||
'border-width',
|
||||
'border-color',
|
||||
'border-top',
|
||||
'border-top-style',
|
||||
'border-top-width',
|
||||
'border-top-color',
|
||||
'border-right',
|
||||
'border-right-style',
|
||||
'border-right-width',
|
||||
'border-right-color',
|
||||
'border-bottom',
|
||||
'border-bottom-style',
|
||||
'border-bottom-width',
|
||||
'border-bottom-color',
|
||||
'border-left',
|
||||
'border-left-style',
|
||||
'border-left-width',
|
||||
'border-left-color',
|
||||
'border-radius',
|
||||
'text-align',
|
||||
'text-justify',
|
||||
'text-indent',
|
||||
'text-overflow',
|
||||
'text-decoration',
|
||||
'white-space',
|
||||
'color',
|
||||
'background',
|
||||
'background-position',
|
||||
'background-repeat',
|
||||
'background-size',
|
||||
'background-color',
|
||||
'background-clip',
|
||||
'opacity',
|
||||
'filter',
|
||||
'list-style',
|
||||
'outline',
|
||||
'visibility',
|
||||
'box-shadow',
|
||||
'text-shadow',
|
||||
'resize',
|
||||
'transition'
|
||||
]
|
||||
}
|
||||
};
|
75
sub-government-screen-service/auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
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 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 shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
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')
|
||||
}
|
23
sub-government-screen-service/components.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
BaseBg: typeof import('./src/components/baseBg.vue')['default']
|
||||
CodeDialog: typeof import('./src/components/code-dialog/index.vue')['default']
|
||||
CustomCard: typeof import('./src/components/CustomCard.vue')['default']
|
||||
CustomSelect: typeof import('./src/components/CustomSelect.vue')['default']
|
||||
GridSelect: typeof import('./src/components/GridSelect.vue')['default']
|
||||
LandClassificationType: typeof import('./src/components/LandClassificationType.vue')['default']
|
||||
LandIsTransfer: typeof import('./src/components/LandIsTransfer.vue')['default']
|
||||
LandType: typeof import('./src/components/LandType.vue')['default']
|
||||
Pagina: typeof import('./src/components/Pagina.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SubTop: typeof import('./src/components/subTop.vue')['default']
|
||||
}
|
||||
}
|
16
sub-government-screen-service/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/logo.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>数据大屏</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
76
sub-government-screen-service/package.json
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "government-affairs-service",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --mode development",
|
||||
"build": "vite build --mode production",
|
||||
"test": "vite build --mode test",
|
||||
"preview": "vite preview",
|
||||
"format": "prettier --write 'src/**/*.{vue,ts,tsx,js,jsx,css,less,scss,json,md}'",
|
||||
"eslint": "npx eslint --init",
|
||||
"lint": "npm run lint:script && npm run lint:style",
|
||||
"lint:style": "stylelint 'src/**/*.{vue,scss,css,sass,less}' --fix",
|
||||
"lint:script": "eslint --ext .js,.ts,.tsx,.vue --fix --quiet ./src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@smallwei/avue": "^3.6.2",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.6.5",
|
||||
"echarts": "^5.6.0",
|
||||
"element-plus": "^2.7.2",
|
||||
"js-base64": "^3.7.6",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"screenfull": "^6.0.2",
|
||||
"vue": "^3.3.11",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue3-scroll-seamless": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.7",
|
||||
"@babel/eslint-parser": "^7.23.3",
|
||||
"@types/path-browserify": "^1.0.2",
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-vue": "^9.20.1",
|
||||
"mockjs": "^1.1.0",
|
||||
"postcss": "^8.4.33",
|
||||
"postcss-html": "^1.6.0",
|
||||
"postcss-import": "^16.0.0",
|
||||
"prettier": "^3.2.4",
|
||||
"sass": "^1.70.0",
|
||||
"stylelint": "^16.2.0",
|
||||
"stylelint-config-html": "^1.1.0",
|
||||
"stylelint-config-prettier": "^9.0.5",
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-config-recommended": "^14.0.0",
|
||||
"stylelint-config-recommended-scss": "^14.0.0",
|
||||
"stylelint-config-recommended-vue": "^1.5.0",
|
||||
"stylelint-config-standard": "^36.0.0",
|
||||
"stylelint-config-standard-scss": "^13.0.0",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"stylelint-scss": "^6.1.0",
|
||||
"terser": "^5.27.0",
|
||||
"unplugin-auto-import": "^0.17.3",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"vite": "^5.0.8",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-mock": "^3.0.1",
|
||||
"vite-plugin-progress": "^0.0.7",
|
||||
"vite-plugin-qiankun": "^1.0.15",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0"
|
||||
}
|
||||
}
|
BIN
sub-government-screen-service/public/images/avatar.gif
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
sub-government-screen-service/public/logo.png
Normal file
After Width: | Height: | Size: 12 KiB |
27
sub-government-screen-service/src/App.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2024-01-24 18:54:01
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2025-02-28 11:31:12
|
||||
-->
|
||||
<template>
|
||||
<el-config-provider :size="size" :locale="zhCn">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup name="app">
|
||||
import { computed } from 'vue';
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
// 配置element中文
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
|
||||
const SettingStore = useSettingStore();
|
||||
// 配置全局组件大小
|
||||
const size = computed(() => SettingStore.themeConfig.globalComSize);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './styles/style';
|
||||
</style>
|
109
sub-government-screen-service/src/apis/baseInfo.js
Normal file
@ -0,0 +1,109 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
//基础信息维护——字典项管理
|
||||
|
||||
//种植产物相关
|
||||
// #region
|
||||
export function getPlanCrop(params = {}) {
|
||||
return request('land-resource/baseInfo/planTypePage', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function savePlanCrop(data) {
|
||||
return request('land-resource/baseInfo/planTypeSave', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function upPlanCrop(data = {}) {
|
||||
return request('land-resource/baseInfo/planTypeEdit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function exportPlanCrop(params = {}) {
|
||||
return request('/land-resource/baseInfo/planTypeExport', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function delPlanCrop(params) {
|
||||
return request('land-resource/baseInfo/planTypeDelete/' + params.id, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
//种植产物对应的种植阶段相关
|
||||
// #region
|
||||
// export function getPlanStage(params = {}) {
|
||||
// return request('land-resource/baseInfo/planTypePage', {
|
||||
// method: 'GET',
|
||||
// params,
|
||||
// });
|
||||
// }
|
||||
|
||||
// export function upPlanStage(data = {}) {
|
||||
// return request('land-resource/baseInfo/planTypeEdit', {
|
||||
// method: 'PUT',
|
||||
// data,
|
||||
// });
|
||||
// }
|
||||
|
||||
// export function exportPlanStage(params = {}) {
|
||||
// return request('/land-resource/baseInfo/planTypeExport', {
|
||||
// method: 'GET',
|
||||
// params,
|
||||
// responseType: 'blob',
|
||||
// });
|
||||
// }
|
||||
|
||||
// export function delPlanStage(params) {
|
||||
// return request('land-resource/baseInfo/planTypeDelete/' + params.id, {
|
||||
// method: 'DELETE',
|
||||
// });
|
||||
// }
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region
|
||||
|
||||
export function savePlanStage(data) {
|
||||
return request('land-resource/baseInfo/stageTypeSave', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/* ------ ------ */
|
||||
|
||||
/* 获取土壤类型列表 */
|
||||
export function getSoilType(params) {
|
||||
return request('land-resource/baseInfo/soilTypePage', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
/* 创建土壤类型 */
|
||||
export function saveSoilType(data) {
|
||||
return request('land-resource/baseInfo/soilTypeSave', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/* 编辑土壤类型 */
|
||||
export function updateSoilType(data) {
|
||||
return request('land-resource/baseInfo/soilTypeSave', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
// #endregion
|
1
sub-government-screen-service/src/apis/casualLandApi.js
Normal file
@ -0,0 +1 @@
|
||||
import request from '@/utils/request';
|
81
sub-government-screen-service/src/apis/coding.js
Normal file
@ -0,0 +1,81 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
/**
|
||||
* @Title: 列表
|
||||
*/
|
||||
export function GetEntityList(params = {}) {
|
||||
return request('/trace/code/farmMange/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 新增
|
||||
*/
|
||||
export function AddEntity(data = {}) {
|
||||
return request('/trace/code/farmMange/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 修改
|
||||
*/
|
||||
export function UpdateEntity(data = {}) {
|
||||
return request('/trace/code/farmMange/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 删除
|
||||
*/
|
||||
export function DeleteEntity(params = {}) {
|
||||
return request('/trace/code/farmMange/delete', {
|
||||
method: 'DELETE',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 导入
|
||||
*/
|
||||
export function ImportEntity(data = {}) {
|
||||
return request('/trace/code/farmMange/import', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 导出
|
||||
*/
|
||||
export function ExportEntity(params = {}) {
|
||||
return request('/trace/code/farmMange/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 采收详情
|
||||
*/
|
||||
export function GetEntity(params = {}) {
|
||||
return request(`/trace/code/farmMange/qualityCheck/${params?.id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 溯源详情
|
||||
*/
|
||||
export function GetTraceDetail(params = {}) {
|
||||
return request(`/trace/code/farmMange/originalCodeInfo/${params?.id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
51
sub-government-screen-service/src/apis/grid.js
Normal file
@ -0,0 +1,51 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
/**
|
||||
* @Title: 列表
|
||||
*/
|
||||
export function GetEntityList(params = {}) {
|
||||
return request('/land-resource/gridManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 新增
|
||||
*/
|
||||
export function AddEntity(data = {}) {
|
||||
return request('/land-resource/gridManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 修改
|
||||
*/
|
||||
export function UpdateEntity(data = {}) {
|
||||
return request('/land-resource/gridManage/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 删除
|
||||
*/
|
||||
export function DeleteEntity(params = {}) {
|
||||
return request(`/land-resource/gridManage/delete/${params.id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 导出
|
||||
*/
|
||||
export function ExportEntity(params = {}) {
|
||||
return request('/land-resource/gridManage/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
35
sub-government-screen-service/src/apis/index.js
Normal file
@ -0,0 +1,35 @@
|
||||
import request from '@/utils/axios';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
/**
|
||||
* @Title: 获取字典
|
||||
*/
|
||||
export function CommonDicData(params = { pageNum: 1, pageSize: 20, dictType: null }) {
|
||||
if (isEmpty(params?.dictType)) return;
|
||||
return request(`/system/dict/data/list`, {
|
||||
method: 'GET',
|
||||
apisType: 'dicData',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 上传图片
|
||||
*/
|
||||
export function CommonUpload(data, params) {
|
||||
return request(`/upload`, {
|
||||
method: 'POST',
|
||||
apisType: 'upload',
|
||||
uploadType: 'multipart/form-data',
|
||||
data,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
//云南省所有区域信息
|
||||
export function getRegion(code) {
|
||||
let codeVal = code ? code : '530000';
|
||||
return request('/system/area/region?areaCode=' + codeVal, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
import * as redBlack from './redAndBlank';
|
||||
|
||||
export { redBlack };
|
@ -0,0 +1 @@
|
||||
import request from '@/utils/request';
|
258
sub-government-screen-service/src/apis/land.js
Normal file
@ -0,0 +1,258 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
/* 土地列表 */
|
||||
export function getLandsList(params = {}) {
|
||||
return request('land-resource/landManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function saveLand(data = {}) {
|
||||
return request('land-resource/landManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
export function exportLands(params = {}) {
|
||||
return request('/land-resource/landManage/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
//年度计划相关
|
||||
export function getAnnualList(params = {}) {
|
||||
return request('land-resource/annualManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function saveAnnual(data) {
|
||||
return request('land-resource/annualManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
export function editAnnual(data = {}) {
|
||||
return request('land-resource/annualManage/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
export function examineAnnual(data = {}) {
|
||||
return request('land-resource/annualManage/exam', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function exportAnnua(params = {}) {
|
||||
return request('/land-resource/annualManage/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function delAnnual(params) {
|
||||
return request('land-resource/annualManage/delete/' + params.id, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
//种植规划相关
|
||||
export function getPlanList(params = {}) {
|
||||
return request('land-resource/planManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function savePlan(data) {
|
||||
return request('land-resource/planManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function editAlan(data = {}) {
|
||||
return request('land-resource/planManage/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function exportPlan(params = {}) {
|
||||
return request('/land-resource/planManage/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function delPlan(params) {
|
||||
return request('land-resource/planManage/delete/' + params.id, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
//种植阶段相关
|
||||
export function getPlantingStage(params = {}) {
|
||||
return request('land-resource/planManage/pageStage', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function savePlantingStage(data) {
|
||||
return request('land-resource/planManage/stageSave', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function editPlantingStage(data = {}) {
|
||||
return request('land-resource/planManage/editStage', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function delPlantingStage(params) {
|
||||
return request('land-resource/planManage/deleteStage/' + params.id, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
/* 删除土地 */
|
||||
export function delLand(id) {
|
||||
return request('land-resource/landManage/delete/' + id, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
//作业记录相关
|
||||
export function getOperationRecord(params = {}) {
|
||||
return request('land-resource/operationRecord/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function saveOperationRecord(data) {
|
||||
return request('land-resource/operationRecord/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function editOperationRecord(data = {}) {
|
||||
return request('land-resource/operationRecord/update', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function delOperationRecord(id) {
|
||||
return request('land-resource/operationRecord/delete/' + id, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
export function exportOperationRecord(params = {}) {
|
||||
return request('/land-resource/operationRecord/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
export function importOperationRecord(data = {}) {
|
||||
return request('/land-resource/operationRecord/import', {
|
||||
method: 'POST',
|
||||
data,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
}
|
||||
|
||||
//通过土地获取产物和位置
|
||||
export function getAddrCropByLand(landId) {
|
||||
return request('land-resource/operationRecord/workArea/' + landId, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
/* 导入土地 */
|
||||
export function importLands(data) {
|
||||
return request('land-resource/landManage/import', {
|
||||
method: 'POST',
|
||||
data,
|
||||
Headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
//土地巡查相关
|
||||
export function getlandInspection(params = {}) {
|
||||
return request('land-resource/landInspection/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function savelandInspection(data) {
|
||||
return request('land-resource/landInspection/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function enrolllandInspection(data = {}) {
|
||||
return request('land-resource/landInspection/registrationResult', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function exportlandInspection(params = {}) {
|
||||
return request('/land-resource/landInspection/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
/* ------ 土地违法处理 ------ */
|
||||
// #region
|
||||
|
||||
/* 查询土地违法处理 */
|
||||
export function getLandIllegal(params = {}) {
|
||||
return request('land-resource/landViolation/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
/* 新增土地违法处理 */
|
||||
export function createLandIllegal(data = {}) {
|
||||
return request('land-resource/landViolation/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/* 登记处理 */
|
||||
export function registerLandIllegal(data = {}) {
|
||||
return request('land-resource/landViolation/registResult', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
/* 违法详情 */
|
||||
export function illegalInfo(id = '') {
|
||||
return request('land-resource/landViolation/detail/' + id, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
// #endregion
|
61
sub-government-screen-service/src/apis/plan.js
Normal file
@ -0,0 +1,61 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
/**
|
||||
* @Title: 列表
|
||||
*/
|
||||
export function GetEntityList(params = {}) {
|
||||
return request('/land-resource/annualManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 新增
|
||||
*/
|
||||
export function AddEntity(data = {}) {
|
||||
return request('/land-resource/annualManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 修改
|
||||
*/
|
||||
export function UpdateEntity(data = {}) {
|
||||
return request('/land-resource/annualManage/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 审核
|
||||
*/
|
||||
export function AuditEntity(data = {}) {
|
||||
return request('/land-resource/annualManage/exam', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 删除
|
||||
*/
|
||||
export function DeleteEntity(params = {}) {
|
||||
return request(`/land-resource/annualManage/delete/${params.id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 导出
|
||||
*/
|
||||
export function ExportEntity(params = {}) {
|
||||
return request('/land-resource/annualManage/export', {
|
||||
method: 'GET',
|
||||
params,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
41
sub-government-screen-service/src/apis/quality.js
Normal file
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
/**
|
||||
* @Title: 列表
|
||||
*/
|
||||
export function GetEntityList(params) {
|
||||
return request('/trace/code/qualityManage/page', {
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 新增
|
||||
*/
|
||||
export function AddEntity(data) {
|
||||
return request('/trace/code/qualityManage/save', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 修改
|
||||
*/
|
||||
export function UpdateEntity(data) {
|
||||
return request('/trace/code/qualityManage/edit', {
|
||||
method: 'PUT',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 删除
|
||||
*/
|
||||
export function DeleteEntity(params) {
|
||||
return request('/trace/code/qualityManage/delete', {
|
||||
method: 'DELETE',
|
||||
params,
|
||||
});
|
||||
}
|
53
sub-government-screen-service/src/apis/user.js
Normal file
@ -0,0 +1,53 @@
|
||||
import request from '@/utils/axios';
|
||||
|
||||
/**
|
||||
* @Title: 列表
|
||||
*/
|
||||
export function GetEntityList(data, params) {
|
||||
return request('/store/user/query-user', {
|
||||
method: 'POST',
|
||||
data: data,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 新增
|
||||
*/
|
||||
export function AddEntity(data, params = {}) {
|
||||
return request('/store/user/add-user', {
|
||||
method: 'POST',
|
||||
data: data,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 修改
|
||||
*/
|
||||
export function UpdateEntity(data, params = {}) {
|
||||
return request('/store/user/update-user', {
|
||||
method: 'PUT',
|
||||
data: data,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @Title: 删除
|
||||
*/
|
||||
export function DeleteEntity(data, params) {
|
||||
return request('/store/user/del-user', {
|
||||
method: 'DELETE',
|
||||
data: data,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
export function UploadAvatar(data, params) {
|
||||
return request('/store/self/generate-avatar-pic-upload-url', {
|
||||
method: 'POST',
|
||||
data: data,
|
||||
params: params,
|
||||
});
|
||||
}
|
539
sub-government-screen-service/src/assets/fonts/demo.css
Normal file
@ -0,0 +1,539 @@
|
||||
/* Logo 字体 */
|
||||
@font-face {
|
||||
font-family: "iconfont logo";
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "iconfont logo";
|
||||
font-size: 160px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#tabs li {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
#tabs .active {
|
||||
border-bottom-color: #f00;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.tab-container .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 页面布局 */
|
||||
.main {
|
||||
padding: 30px 100px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main .logo {
|
||||
color: #333;
|
||||
text-align: left;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1;
|
||||
height: 110px;
|
||||
margin-top: -50px;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
font-size: 160px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.helps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.helps pre {
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: solid 1px #e7e1cd;
|
||||
background-color: #fffdef;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon_lists {
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.icon_lists li {
|
||||
width: 100px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
list-style: none !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.icon_lists li .code-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon_lists .icon {
|
||||
display: block;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
font-size: 42px;
|
||||
margin: 10px auto;
|
||||
color: #333;
|
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
transition: font-size 0.25s linear, width 0.25s linear;
|
||||
}
|
||||
|
||||
.icon_lists .icon:hover {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.icon_lists .svg-icon {
|
||||
/* 通过设置 font-size 来改变图标大小 */
|
||||
width: 1em;
|
||||
/* 图标和文字相邻时,垂直对齐 */
|
||||
vertical-align: -0.15em;
|
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||
fill: currentColor;
|
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||
normalize.css 中也包含这行 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon_lists li .name,
|
||||
.icon_lists li .code-name {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* markdown 样式 */
|
||||
.markdown {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown img {
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
color: #404040;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4,
|
||||
.markdown h5,
|
||||
.markdown h6 {
|
||||
color: #404040;
|
||||
margin: 1.6em 0 0.6em 0;
|
||||
font-weight: 500;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
background: #e9e9e9;
|
||||
margin: 16px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown>p,
|
||||
.markdown>blockquote,
|
||||
.markdown>.highlight,
|
||||
.markdown>ol,
|
||||
.markdown>ul {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.markdown ul>li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
.markdown>ul li,
|
||||
.markdown blockquote ul>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown>ul li p,
|
||||
.markdown>ol li p {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
|
||||
.markdown ol>li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.markdown>ol li,
|
||||
.markdown blockquote ol>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
margin: 0 3px;
|
||||
padding: 0 5px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown strong,
|
||||
.markdown b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
empty-cells: show;
|
||||
border: 1px solid #e9e9e9;
|
||||
width: 95%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
white-space: nowrap;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table th,
|
||||
.markdown>table td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-size: 90%;
|
||||
color: #999;
|
||||
border-left: 4px solid #e9e9e9;
|
||||
padding-left: 0.8em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown .anchor {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.markdown .waiting {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.markdown h1:hover .anchor,
|
||||
.markdown h2:hover .anchor,
|
||||
.markdown h3:hover .anchor,
|
||||
.markdown h4:hover .anchor,
|
||||
.markdown h5:hover .anchor,
|
||||
.markdown h6:hover .anchor {
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown>br,
|
||||
.markdown>p>br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: white;
|
||||
padding: 0.5em;
|
||||
color: #333333;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 代码高亮 */
|
||||
/* PrismJS 1.15.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre)>code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre)>code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
1223
sub-government-screen-service/src/assets/fonts/demo_index.html
Normal file
195
sub-government-screen-service/src/assets/fonts/iconfont.css
Normal file
@ -0,0 +1,195 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4425172 */
|
||||
src: url('iconfont.woff2?t=1725879404188') format('woff2'),
|
||||
url('iconfont.woff?t=1725879404188') format('woff'),
|
||||
url('iconfont.ttf?t=1725879404188') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-data4:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
|
||||
.icon-data5:before {
|
||||
content: "\e6be";
|
||||
}
|
||||
|
||||
.icon-recharge-record:before {
|
||||
content: "\e614";
|
||||
}
|
||||
|
||||
.icon-recharge-rule:before {
|
||||
content: "\e628";
|
||||
}
|
||||
|
||||
.icon-user-profile:before {
|
||||
content: "\e783";
|
||||
}
|
||||
|
||||
.icon-achieve:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.icon-activity-level:before {
|
||||
content: "\e61a";
|
||||
}
|
||||
|
||||
.icon-skins:before {
|
||||
content: "\e790";
|
||||
}
|
||||
|
||||
.icon-data1:before {
|
||||
content: "\e996";
|
||||
}
|
||||
|
||||
.icon-data2:before {
|
||||
content: "\e661";
|
||||
}
|
||||
|
||||
.icon-data3:before {
|
||||
content: "\e632";
|
||||
}
|
||||
|
||||
.icon-data:before {
|
||||
content: "\e64e";
|
||||
}
|
||||
|
||||
.icon-game:before {
|
||||
content: "\e6d0";
|
||||
}
|
||||
|
||||
.icon-banner:before {
|
||||
content: "\e613";
|
||||
}
|
||||
|
||||
.icon-verification:before {
|
||||
content: "\e601";
|
||||
}
|
||||
|
||||
.icon-balance:before {
|
||||
content: "\e6b9";
|
||||
}
|
||||
|
||||
.icon-refund:before {
|
||||
content: "\e7af";
|
||||
}
|
||||
|
||||
.icon-wechat:before {
|
||||
content: "\e681";
|
||||
}
|
||||
|
||||
.icon-alipay:before {
|
||||
content: "\e61e";
|
||||
}
|
||||
|
||||
.icon-user:before {
|
||||
content: "\e67f";
|
||||
}
|
||||
|
||||
.icon-coupon:before {
|
||||
content: "\e65a";
|
||||
}
|
||||
|
||||
.icon-level:before {
|
||||
content: "\e7d8";
|
||||
}
|
||||
|
||||
.icon-activity:before {
|
||||
content: "\e67b";
|
||||
}
|
||||
|
||||
.icon-shop:before {
|
||||
content: "\e60a";
|
||||
}
|
||||
|
||||
.icon-member:before {
|
||||
content: "\e640";
|
||||
}
|
||||
|
||||
.icon-recharge:before {
|
||||
content: "\e799";
|
||||
}
|
||||
|
||||
.icon-marketing:before {
|
||||
content: "\e765";
|
||||
}
|
||||
|
||||
.icon-goods-sku:before {
|
||||
content: "\e6d7";
|
||||
}
|
||||
|
||||
.icon-store:before {
|
||||
content: "\e62b";
|
||||
}
|
||||
|
||||
.icon-goods-store:before {
|
||||
content: "\e6c6";
|
||||
}
|
||||
|
||||
.icon-storer:before {
|
||||
content: "\e64a";
|
||||
}
|
||||
|
||||
.icon-order:before {
|
||||
content: "\e737";
|
||||
}
|
||||
|
||||
.icon-permission:before {
|
||||
content: "\e612";
|
||||
}
|
||||
|
||||
.icon-goods:before {
|
||||
content: "\e889";
|
||||
}
|
||||
|
||||
.icon-menu:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
|
||||
.icon-dict-type:before {
|
||||
content: "\e652";
|
||||
}
|
||||
|
||||
.icon-dictionary:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
.icon-role:before {
|
||||
content: "\e604";
|
||||
}
|
||||
|
||||
.icon-fullscreen:before {
|
||||
content: "\e8fa";
|
||||
}
|
||||
|
||||
.icon-exit-fullscreen:before {
|
||||
content: "\e8fb";
|
||||
}
|
||||
|
||||
.icon-table:before {
|
||||
content: "\e615";
|
||||
}
|
||||
|
||||
.icon-test:before {
|
||||
content: "\e610";
|
||||
}
|
||||
|
||||
.icon-lang:before {
|
||||
content: "\e649";
|
||||
}
|
||||
|
||||
.icon-demo:before {
|
||||
content: "\e6ee";
|
||||
}
|
||||
|
||||
.icon-size:before {
|
||||
content: "\e660";
|
||||
}
|
||||
|
324
sub-government-screen-service/src/assets/fonts/iconfont.json
Normal file
@ -0,0 +1,324 @@
|
||||
{
|
||||
"id": "4425172",
|
||||
"name": "sub-vue",
|
||||
"font_family": "iconfont",
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "react/vue项目后台管理平台",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "1218184",
|
||||
"name": "销售明细",
|
||||
"font_class": "data4",
|
||||
"unicode": "e60c",
|
||||
"unicode_decimal": 58892
|
||||
},
|
||||
{
|
||||
"icon_id": "2230090",
|
||||
"name": "销售明细",
|
||||
"font_class": "data5",
|
||||
"unicode": "e6be",
|
||||
"unicode_decimal": 59070
|
||||
},
|
||||
{
|
||||
"icon_id": "6882983",
|
||||
"name": "充值记录",
|
||||
"font_class": "recharge-record",
|
||||
"unicode": "e614",
|
||||
"unicode_decimal": 58900
|
||||
},
|
||||
{
|
||||
"icon_id": "34611004",
|
||||
"name": "充值规则",
|
||||
"font_class": "recharge-rule",
|
||||
"unicode": "e628",
|
||||
"unicode_decimal": 58920
|
||||
},
|
||||
{
|
||||
"icon_id": "15562252",
|
||||
"name": "用户画像",
|
||||
"font_class": "user-profile",
|
||||
"unicode": "e783",
|
||||
"unicode_decimal": 59267
|
||||
},
|
||||
{
|
||||
"icon_id": "18747445",
|
||||
"name": "成就",
|
||||
"font_class": "achieve",
|
||||
"unicode": "e616",
|
||||
"unicode_decimal": 58902
|
||||
},
|
||||
{
|
||||
"icon_id": "33848542",
|
||||
"name": "我的-段位",
|
||||
"font_class": "activity-level",
|
||||
"unicode": "e61a",
|
||||
"unicode_decimal": 58906
|
||||
},
|
||||
{
|
||||
"icon_id": "20406821",
|
||||
"name": "皮肤",
|
||||
"font_class": "skins",
|
||||
"unicode": "e790",
|
||||
"unicode_decimal": 59280
|
||||
},
|
||||
{
|
||||
"icon_id": "2214847",
|
||||
"name": "个人中心-积分商城",
|
||||
"font_class": "data1",
|
||||
"unicode": "e996",
|
||||
"unicode_decimal": 59798
|
||||
},
|
||||
{
|
||||
"icon_id": "14233304",
|
||||
"name": "价值投资",
|
||||
"font_class": "data2",
|
||||
"unicode": "e661",
|
||||
"unicode_decimal": 58977
|
||||
},
|
||||
{
|
||||
"icon_id": "23059951",
|
||||
"name": "费用统计",
|
||||
"font_class": "data3",
|
||||
"unicode": "e632",
|
||||
"unicode_decimal": 58930
|
||||
},
|
||||
{
|
||||
"icon_id": "2199049",
|
||||
"name": "数据报表",
|
||||
"font_class": "data",
|
||||
"unicode": "e64e",
|
||||
"unicode_decimal": 58958
|
||||
},
|
||||
{
|
||||
"icon_id": "36257316",
|
||||
"name": "游戏管理",
|
||||
"font_class": "game",
|
||||
"unicode": "e6d0",
|
||||
"unicode_decimal": 59088
|
||||
},
|
||||
{
|
||||
"icon_id": "11913396",
|
||||
"name": "banner",
|
||||
"font_class": "banner",
|
||||
"unicode": "e613",
|
||||
"unicode_decimal": 58899
|
||||
},
|
||||
{
|
||||
"icon_id": "35264323",
|
||||
"name": "核销码核销",
|
||||
"font_class": "verification",
|
||||
"unicode": "e601",
|
||||
"unicode_decimal": 58881
|
||||
},
|
||||
{
|
||||
"icon_id": "6514128",
|
||||
"name": "结算管理",
|
||||
"font_class": "balance",
|
||||
"unicode": "e6b9",
|
||||
"unicode_decimal": 59065
|
||||
},
|
||||
{
|
||||
"icon_id": "12025983",
|
||||
"name": "退货退款",
|
||||
"font_class": "refund",
|
||||
"unicode": "e7af",
|
||||
"unicode_decimal": 59311
|
||||
},
|
||||
{
|
||||
"icon_id": "1207908",
|
||||
"name": "wechat",
|
||||
"font_class": "wechat",
|
||||
"unicode": "e681",
|
||||
"unicode_decimal": 59009
|
||||
},
|
||||
{
|
||||
"icon_id": "27188513",
|
||||
"name": "alipay",
|
||||
"font_class": "alipay",
|
||||
"unicode": "e61e",
|
||||
"unicode_decimal": 58910
|
||||
},
|
||||
{
|
||||
"icon_id": "11111017",
|
||||
"name": "会员",
|
||||
"font_class": "user",
|
||||
"unicode": "e67f",
|
||||
"unicode_decimal": 59007
|
||||
},
|
||||
{
|
||||
"icon_id": "630079",
|
||||
"name": "我的优惠券",
|
||||
"font_class": "coupon",
|
||||
"unicode": "e65a",
|
||||
"unicode_decimal": 58970
|
||||
},
|
||||
{
|
||||
"icon_id": "2046370",
|
||||
"name": "会员等级",
|
||||
"font_class": "level",
|
||||
"unicode": "e7d8",
|
||||
"unicode_decimal": 59352
|
||||
},
|
||||
{
|
||||
"icon_id": "2569868",
|
||||
"name": "活动",
|
||||
"font_class": "activity",
|
||||
"unicode": "e67b",
|
||||
"unicode_decimal": 59003
|
||||
},
|
||||
{
|
||||
"icon_id": "2681698",
|
||||
"name": "门店",
|
||||
"font_class": "shop",
|
||||
"unicode": "e60a",
|
||||
"unicode_decimal": 58890
|
||||
},
|
||||
{
|
||||
"icon_id": "2811147",
|
||||
"name": "会员",
|
||||
"font_class": "member",
|
||||
"unicode": "e640",
|
||||
"unicode_decimal": 58944
|
||||
},
|
||||
{
|
||||
"icon_id": "4560182",
|
||||
"name": "会员充值",
|
||||
"font_class": "recharge",
|
||||
"unicode": "e799",
|
||||
"unicode_decimal": 59289
|
||||
},
|
||||
{
|
||||
"icon_id": "5880283",
|
||||
"name": "营销",
|
||||
"font_class": "marketing",
|
||||
"unicode": "e765",
|
||||
"unicode_decimal": 59237
|
||||
},
|
||||
{
|
||||
"icon_id": "6982618",
|
||||
"name": "商品规格",
|
||||
"font_class": "goods-sku",
|
||||
"unicode": "e6d7",
|
||||
"unicode_decimal": 59095
|
||||
},
|
||||
{
|
||||
"icon_id": "7307041",
|
||||
"name": "商家入驻",
|
||||
"font_class": "store",
|
||||
"unicode": "e62b",
|
||||
"unicode_decimal": 58923
|
||||
},
|
||||
{
|
||||
"icon_id": "11639867",
|
||||
"name": "小店商品库",
|
||||
"font_class": "goods-store",
|
||||
"unicode": "e6c6",
|
||||
"unicode_decimal": 59078
|
||||
},
|
||||
{
|
||||
"icon_id": "13872198",
|
||||
"name": "商家列表",
|
||||
"font_class": "storer",
|
||||
"unicode": "e64a",
|
||||
"unicode_decimal": 58954
|
||||
},
|
||||
{
|
||||
"icon_id": "577335",
|
||||
"name": "订单",
|
||||
"font_class": "order",
|
||||
"unicode": "e737",
|
||||
"unicode_decimal": 59191
|
||||
},
|
||||
{
|
||||
"icon_id": "736503",
|
||||
"name": "权限",
|
||||
"font_class": "permission",
|
||||
"unicode": "e612",
|
||||
"unicode_decimal": 58898
|
||||
},
|
||||
{
|
||||
"icon_id": "1727271",
|
||||
"name": "06商品-线性",
|
||||
"font_class": "goods",
|
||||
"unicode": "e889",
|
||||
"unicode_decimal": 59529
|
||||
},
|
||||
{
|
||||
"icon_id": "7587933",
|
||||
"name": "菜单",
|
||||
"font_class": "menu",
|
||||
"unicode": "e60e",
|
||||
"unicode_decimal": 58894
|
||||
},
|
||||
{
|
||||
"icon_id": "12758820",
|
||||
"name": "dictionary",
|
||||
"font_class": "dict-type",
|
||||
"unicode": "e652",
|
||||
"unicode_decimal": 58962
|
||||
},
|
||||
{
|
||||
"icon_id": "13768112",
|
||||
"name": "dictionary",
|
||||
"font_class": "dictionary",
|
||||
"unicode": "e600",
|
||||
"unicode_decimal": 58880
|
||||
},
|
||||
{
|
||||
"icon_id": "37734141",
|
||||
"name": "new-role",
|
||||
"font_class": "role",
|
||||
"unicode": "e604",
|
||||
"unicode_decimal": 58884
|
||||
},
|
||||
{
|
||||
"icon_id": "1727563",
|
||||
"name": "327全屏",
|
||||
"font_class": "fullscreen",
|
||||
"unicode": "e8fa",
|
||||
"unicode_decimal": 59642
|
||||
},
|
||||
{
|
||||
"icon_id": "1727566",
|
||||
"name": "328退出全屏",
|
||||
"font_class": "exit-fullscreen",
|
||||
"unicode": "e8fb",
|
||||
"unicode_decimal": 59643
|
||||
},
|
||||
{
|
||||
"icon_id": "11641852",
|
||||
"name": "表格",
|
||||
"font_class": "table",
|
||||
"unicode": "e615",
|
||||
"unicode_decimal": 58901
|
||||
},
|
||||
{
|
||||
"icon_id": "20104468",
|
||||
"name": "测试",
|
||||
"font_class": "test",
|
||||
"unicode": "e610",
|
||||
"unicode_decimal": 58896
|
||||
},
|
||||
{
|
||||
"icon_id": "26686335",
|
||||
"name": "中英文",
|
||||
"font_class": "lang",
|
||||
"unicode": "e649",
|
||||
"unicode_decimal": 58953
|
||||
},
|
||||
{
|
||||
"icon_id": "30012547",
|
||||
"name": "方案列表-默认",
|
||||
"font_class": "demo",
|
||||
"unicode": "e6ee",
|
||||
"unicode_decimal": 59118
|
||||
},
|
||||
{
|
||||
"icon_id": "37702310",
|
||||
"name": "文字大小",
|
||||
"font_class": "size",
|
||||
"unicode": "e660",
|
||||
"unicode_decimal": 58976
|
||||
}
|
||||
]
|
||||
}
|
BIN
sub-government-screen-service/src/assets/fonts/iconfont.ttf
Normal file
BIN
sub-government-screen-service/src/assets/fonts/iconfont.woff
Normal file
BIN
sub-government-screen-service/src/assets/fonts/iconfont.woff2
Normal file
BIN
sub-government-screen-service/src/assets/images/bottombj.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
sub-government-screen-service/src/assets/images/gmmap.png
Normal file
After Width: | Height: | Size: 170 KiB |
BIN
sub-government-screen-service/src/assets/images/screenbg.png
Normal file
After Width: | Height: | Size: 285 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.6 KiB |
BIN
sub-government-screen-service/src/assets/template/采收赋码-导入模板.xlsx
Normal file
21
sub-government-screen-service/src/components/CustomCard.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<el-card body-class="custom_content_card_" :shadow="props.shadow">
|
||||
<slot></slot>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
shadow: {
|
||||
type: String,
|
||||
default: 'never',
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.el-card:has(.custom_content_card_) {
|
||||
border: none !important;
|
||||
border-radius: 10px !important;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<el-select-v2
|
||||
v-model="val"
|
||||
:options="options"
|
||||
:placeholder="props.set.placeholder"
|
||||
:props="props.set.props"
|
||||
:multiple="props.set.multiple"
|
||||
@change="handleSelect"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import request from '@/utils/axios';
|
||||
const emit = defineEmits(['update:value']);
|
||||
|
||||
const props = defineProps({
|
||||
set: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
url: '',
|
||||
options: [
|
||||
{
|
||||
value: '1',
|
||||
label: 'label 1',
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: 'label 2',
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
label: 'label 3',
|
||||
},
|
||||
],
|
||||
props: {
|
||||
value: 'value',
|
||||
label: 'label',
|
||||
},
|
||||
multiple: false,
|
||||
placeholder: '请选择',
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
value: {
|
||||
type: String || Array || null,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if (props.set.multiple) val.value = [];
|
||||
|
||||
if (props.set.url) {
|
||||
let res = await request(props.set.url, {
|
||||
method: 'get',
|
||||
data: { current: 1, size: 9999 },
|
||||
});
|
||||
if (res.code == 200) {
|
||||
options.value = res.data.records;
|
||||
}
|
||||
} else {
|
||||
options.value = props.set.options;
|
||||
}
|
||||
});
|
||||
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
const val = ref(null);
|
||||
watch(
|
||||
() => props.value,
|
||||
() => {
|
||||
val.value = props.value;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
const options = ref([]);
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
function handleSelect(val_) {
|
||||
emit('update:value', val_);
|
||||
}
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
44
sub-government-screen-service/src/components/GridSelect.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<el-select-v2 v-model="val" :options="options" placeholder="请选择网格" :props="_props" @change="handleSelect" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { GetEntityList } from '@/apis/grid.js';
|
||||
const emit = defineEmits(['update:value']);
|
||||
|
||||
const props = defineProps({
|
||||
// 父组件传过来的值
|
||||
value: {
|
||||
type: String || null,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
let res = await GetEntityList();
|
||||
if (res.code == 200) {
|
||||
options.value = res.data.records;
|
||||
}
|
||||
});
|
||||
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
const val = ref(null);
|
||||
const options = ref([]);
|
||||
const _props = {
|
||||
value: 'id',
|
||||
label: 'productName',
|
||||
};
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
function handleSelect(val_) {
|
||||
emit('update:value', val_);
|
||||
}
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<el-select v-model="val" @change="change">
|
||||
<el-option v-for="item in options" :key="`land_type_${item.value}`" :value="item.value" :label="item.label" :placeholder="props.placeholder">
|
||||
{{ item.label }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 父组件传过来的值
|
||||
value: {
|
||||
type: String || Number || null,
|
||||
default: null,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择',
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['update:value']);
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
|
||||
const val = ref(null);
|
||||
watch(
|
||||
() => props.value,
|
||||
() => {
|
||||
val.value = props.value || props.value == 0 ? String(props.value) : null;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
const options = ref([
|
||||
{ label: '耕地', value: '0' },
|
||||
{ label: '果园', value: '1' },
|
||||
{ label: '茶园', value: '2' },
|
||||
{ label: '其他园地', value: '3' },
|
||||
{ label: '林地', value: '4' },
|
||||
{ label: '草地', value: '5' },
|
||||
{ label: '其他农用地', value: '6' },
|
||||
{ label: '农村宅基地', value: '7' },
|
||||
]);
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
function change(val_) {
|
||||
val.value = val_;
|
||||
emit('update:value', val_);
|
||||
}
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<el-select v-model="val" @change="change">
|
||||
<el-option v-for="item in options" :key="`land_type_${item.value}`" :value="item.value" :label="item.label" :placeholder="props.placeholder">
|
||||
{{ item.label }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 父组件传过来的值
|
||||
value: {
|
||||
type: String || Number || null,
|
||||
default: null,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择',
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['update:value']);
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
|
||||
const val = ref(null);
|
||||
watch(
|
||||
() => props.value,
|
||||
() => {
|
||||
val.value = props.value || props.value == 0 ? String(props.value) : null;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
const options = ref([
|
||||
{ label: '是', value: '0' },
|
||||
{ label: '否', value: '1' },
|
||||
]);
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
function change(val_) {
|
||||
val.value = val_;
|
||||
emit('update:value', val_);
|
||||
}
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
55
sub-government-screen-service/src/components/LandType.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<el-select v-model="val" @change="change">
|
||||
<el-option v-for="item in options" :key="`land_type_${item.value}`" :value="item.value" :label="item.label" :placeholder="props.placeholder">
|
||||
{{ item.label }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 父组件传过来的值
|
||||
value: {
|
||||
type: String || Number || null,
|
||||
default: null,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择',
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['update:value']);
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
|
||||
const val = ref(null);
|
||||
watch(
|
||||
() => props.value,
|
||||
() => {
|
||||
val.value = props.value || props.value == 0 ? String(props.value) : null;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
const options = ref([
|
||||
{ label: '农用地', value: '0' },
|
||||
{ label: '住宅用地', value: '1' },
|
||||
{ label: '园林', value: '2' },
|
||||
]);
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
function change(val_) {
|
||||
val.value = val_;
|
||||
emit('update:value', val_);
|
||||
}
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
72
sub-government-screen-service/src/components/Pagina.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<section :style="{ '--right': props.right ? 'flex-end' : 'unset' }">
|
||||
<el-pagination
|
||||
v-model:current-page="curPage"
|
||||
v-model:page-size="curSize"
|
||||
:page-sizes="[10, 20, 30, 40, 50, 100]"
|
||||
background
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="curTotal"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
pageData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [10, 20, 30, 40, 50, 100];
|
||||
},
|
||||
},
|
||||
right: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['pageChange', 'sizeChange']);
|
||||
const curPage = ref(1);
|
||||
const curSize = ref(10);
|
||||
const curTotal = ref(0);
|
||||
watch(
|
||||
() => props.pageData,
|
||||
() => {
|
||||
curPage.value = props.pageData.page || 1;
|
||||
curSize.value = props.pageData.size || 10;
|
||||
curTotal.value = props.pageData.total || 0;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
function handleCurrentChange(val) {
|
||||
emit('pageChange', val);
|
||||
}
|
||||
|
||||
function handleSizeChange(val) {
|
||||
emit('sizeChange', val);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
section {
|
||||
display: flex;
|
||||
justify-content: var(--right);
|
||||
}
|
||||
</style>
|
134
sub-government-screen-service/src/components/baseBg.vue
Normal file
@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="data-warp" :style="{ 'background-image': 'url(' + getAssetsFile('images/screenbg.png') + ')' }">
|
||||
<div class="chart-content">
|
||||
<div class="top">头部</div>
|
||||
<div class="content">
|
||||
<slot name="center"></slot>
|
||||
</div>
|
||||
<div class="bottom" :style="{ 'background-image': 'url(' + getAssetsFile('images/bottombj.jpg') + ')' }">
|
||||
<div class="b-nav">
|
||||
<div
|
||||
v-for="n in navlist"
|
||||
:key="n.name"
|
||||
class="b-nav-item"
|
||||
:class="currentName == n.name ? 'nav-act' : 'nav-normal'"
|
||||
@click="itemAct(n.name)"
|
||||
>
|
||||
<!-- <router-link :to="n.name"> -->
|
||||
<span>{{ n.title }}</span>
|
||||
<!-- </router-link> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { isEmpty, getAssetsFile } from '@/utils';
|
||||
import { ref, reactive, onMounted, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useApp } from '@/hooks';
|
||||
const router = useRouter();
|
||||
const props = defineProps({
|
||||
nameVal: {
|
||||
type: String,
|
||||
default: 'home',
|
||||
},
|
||||
});
|
||||
|
||||
const navlist = ref([
|
||||
{ title: '首页', name: 'home' },
|
||||
{ title: '土地资源', name: 'land' },
|
||||
{ title: '投入品', name: 'inputs' },
|
||||
{ title: '生产经营主体', name: 'entities' },
|
||||
{ title: '智慧种植检测', name: 'plant' },
|
||||
{ title: '智慧养殖检测', name: 'breed' },
|
||||
{ title: '全流程溯源', name: 'trace' },
|
||||
{ title: '产业预警决策', name: 'early' },
|
||||
]);
|
||||
|
||||
let currentName = ref('home');
|
||||
|
||||
watch(
|
||||
() => props.nameVal,
|
||||
() => {
|
||||
currentName.value = props.nameVal;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const itemAct = (name) => {
|
||||
currentName.value = name;
|
||||
router.push({ name: name });
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.data-warp {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.chart-content {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
.top,
|
||||
.content,
|
||||
.bottom {
|
||||
width: 100%;
|
||||
padding: 0 16px;
|
||||
background-size: cover;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.top {
|
||||
height: 55px;
|
||||
}
|
||||
.bottom {
|
||||
height: 98px;
|
||||
text-align: center;
|
||||
|
||||
.b-nav {
|
||||
margin: auto;
|
||||
display: inline-flex;
|
||||
gap: 20px;
|
||||
.b-nav-item {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
span {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
transform: skewX(-13deg);
|
||||
background: linear-gradient(to bottom, '#ff7e5f', '#548fff');
|
||||
-webkit-background-clip: text;
|
||||
|
||||
letter-spacing: 4px;
|
||||
text-shadow: -2px 0 0 1px #add8f1;
|
||||
}
|
||||
|
||||
&.nav-act {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
&.nav-normal {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
height: calc(100% - 153px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="state.visible"
|
||||
draggable
|
||||
title="溯源码"
|
||||
width="40%"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
@close="onClose"
|
||||
>
|
||||
<div class="code-panel">
|
||||
<div class="code-panel-picture">
|
||||
<el-image style="width: 200px; height: 200px" :src="row.orCodeUrl" fit="cover" lazy />
|
||||
</div>
|
||||
<el-button type="primary" @click="downloadFile(row.orCodeUrl, `${row.productName}-溯源码.png`, 'image')"> 下载溯源码</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup name="code-dialog">
|
||||
import { reactive } from 'vue';
|
||||
import { downloadFile } from '@/utils';
|
||||
const props = defineProps({
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['on-close']);
|
||||
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
});
|
||||
|
||||
const onClose = () => {
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
show: () => {
|
||||
state.visible = true;
|
||||
},
|
||||
hide: () => {
|
||||
onClose();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.code {
|
||||
&-panel {
|
||||
padding-bottom: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
50
sub-government-screen-service/src/components/subTop.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div :style="{ 'text-align': pos }" class="title-top-warp">{{ topTitle || '--' }}</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { isEmpty, getAssetsFile } from '@/utils';
|
||||
import { ref, reactive, onMounted, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useApp } from '@/hooks';
|
||||
|
||||
const router = useRouter();
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '统计分析',
|
||||
},
|
||||
postion: {
|
||||
type: String,
|
||||
default: 'left',
|
||||
},
|
||||
});
|
||||
|
||||
let topTitle = ref('');
|
||||
let pos = ref('');
|
||||
|
||||
watch(
|
||||
() => (props.title, props.postion),
|
||||
() => {
|
||||
topTitle.value = props.title;
|
||||
pos.value = props.postion;
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.title-top-warp {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
transform: skewX(-13deg);
|
||||
background: linear-gradient(to bottom, '#ff7e5f', '#548fff');
|
||||
-webkit-background-clip: text;
|
||||
color: #fff;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: -2px 0 0 1px #add8f1;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
42
sub-government-screen-service/src/config/index.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
|
||||
const { VITE_APP_MIAN, VITE_APP_NAME } = import.meta.env;
|
||||
|
||||
export const GenKey = (key, prefix = VITE_APP_NAME) => {
|
||||
prefix = qiankunWindow.__POWERED_BY_QIANKUN__ ? VITE_APP_MIAN : VITE_APP_MIAN;
|
||||
return prefix ? `${prefix}_` + key : key;
|
||||
};
|
||||
|
||||
export const CONSTANTS = {
|
||||
PREFIX: `${VITE_APP_NAME}_`,
|
||||
PRIMARY: '#409eff',
|
||||
};
|
||||
|
||||
export const CRUD_OPTIONS = {
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
indexWidth: 80,
|
||||
selection: true,
|
||||
align: 'center',
|
||||
headerAlign: 'center',
|
||||
gridBtn: false,
|
||||
columnBtn: false,
|
||||
addBtn: true,
|
||||
viewBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
gutter: 20,
|
||||
labelWidth: 150,
|
||||
column: [],
|
||||
menuWidth: 100,
|
||||
actions: [],
|
||||
dialogDrag: true,
|
||||
};
|
||||
|
||||
export const CRUD_VIEW_OPTIONS = {
|
||||
...CRUD_OPTIONS,
|
||||
index: true,
|
||||
addBtn: false,
|
||||
refreshBtn: false,
|
||||
selection: false,
|
||||
menu: false,
|
||||
};
|
32
sub-government-screen-service/src/directives/auth.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @Description: 按钮权限
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2022-08-30 09:42:47
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-30 13:59:50
|
||||
*/
|
||||
|
||||
// import { CACHE_KEY, useCache } from '@/hooks/web/useCache';
|
||||
|
||||
export function useAuth(app) {
|
||||
app.directive('auth', (el, binding) => {
|
||||
// const { wsCache } = useCache();
|
||||
const { value } = binding;
|
||||
const all_permission = '*:*:*';
|
||||
const permissions = []; //wsCache.get(CACHE_KEY.USER).permissions;
|
||||
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const permissionFlag = value;
|
||||
|
||||
const hasAuth = permissions.some((permission) => {
|
||||
return all_permission === permission || permissionFlag.includes(permission);
|
||||
});
|
||||
|
||||
if (!hasAuth) {
|
||||
el.parentNode && el.parentNode.removeChild(el);
|
||||
}
|
||||
} else {
|
||||
// throw new Error('no auth to access it.');
|
||||
}
|
||||
});
|
||||
}
|
9
sub-government-screen-service/src/directives/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
import { useAuth } from './auth';
|
||||
|
||||
/**
|
||||
* 指令:v-xxx
|
||||
* @methods auth 按钮权限,用法: v-auth
|
||||
*/
|
||||
export const registerDirective = (app) => {
|
||||
useAuth(app);
|
||||
};
|
5
sub-government-screen-service/src/hooks/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { getCurrentInstance } from 'vue';
|
||||
|
||||
export const useApp = () => {
|
||||
return getCurrentInstance().appContext?.config?.globalProperties;
|
||||
};
|
22
sub-government-screen-service/src/hooks/useWrapComponents.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { h } from 'vue';
|
||||
|
||||
const wrapperMap = new Map();
|
||||
|
||||
export const useWrapComponents = (Component, route) => {
|
||||
let wrapper;
|
||||
if (Component) {
|
||||
const wrapperName = route.name;
|
||||
if (wrapperMap.has(wrapperName)) {
|
||||
wrapper = wrapperMap.get(wrapperName);
|
||||
} else {
|
||||
wrapper = {
|
||||
name: wrapperName,
|
||||
render() {
|
||||
return h('div', { className: 'layout-main-inner' }, Component);
|
||||
},
|
||||
};
|
||||
wrapperMap.set(wrapperName, wrapper);
|
||||
}
|
||||
return h(wrapper);
|
||||
}
|
||||
};
|
4
sub-government-screen-service/src/layouts/Views.vue
Normal file
@ -0,0 +1,4 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
<script setup name="layout-views"></script>
|
@ -0,0 +1,82 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2025-02-18 09:48:18
|
||||
-->
|
||||
<template>
|
||||
<el-dropdown class="layout-avatar">
|
||||
<span class="el-dropdown-link">
|
||||
<el-avatar :size="30" class="avatar" :src="userInfo.avatar || getAssetsFile('images/avatar.gif')" />
|
||||
<span class="layout-avatar-name">{{ userInfo.userName || '游客' }}</span>
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :command="0"> 当前角色:{{ userInfo.nickName }} </el-dropdown-item>
|
||||
<el-dropdown-item :command="5" divided @click="logOut">
|
||||
<el-icon><SwitchButton /></el-icon>退出登录
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-avatar">
|
||||
import { computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView';
|
||||
import { usePermissionStore } from '@/store/modules/permission';
|
||||
import { getAssetsFile } from '@/utils';
|
||||
import { Logout } from '#/apis/login';
|
||||
|
||||
const router = useRouter();
|
||||
const UserStore = useUserStore();
|
||||
const TagsViewStore = useTagsViewStore();
|
||||
const PermissionStore = usePermissionStore();
|
||||
|
||||
// 用户信息
|
||||
const userInfo = computed(() => UserStore.getUserInfo());
|
||||
|
||||
const logOut = async () => {
|
||||
ElMessageBox.confirm('您是否确认退出登录?', '温馨提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(async () => {
|
||||
Logout().then((res) => {
|
||||
if (res.code === 200) {
|
||||
UserStore.logout();
|
||||
TagsViewStore.clearVisitedView();
|
||||
PermissionStore.clearRoutes();
|
||||
router.push({ path: '/login' });
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '退出登录成功!',
|
||||
});
|
||||
localStorage.removeItem('daimp-front-main_user_store');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout-avatar {
|
||||
&-name {
|
||||
margin-left: 8px;
|
||||
@include ellipsis;
|
||||
}
|
||||
.el-dropdown-link {
|
||||
@include flex-row;
|
||||
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,46 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2025-02-13 16:02:18
|
||||
-->
|
||||
<template>
|
||||
<el-breadcrumb class="layout-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-if="matched[0].meta.title !== '首页'" key="home" :to="{ path: '/' }">
|
||||
<div class="layout-breadcrumb-item">
|
||||
<span class="layout-breadcrumb-title">首页</span>
|
||||
</div>
|
||||
</el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-for="(item, index) in matched" :key="item.name">
|
||||
<span v-if="item.redirect === 'noRedirect' || index == matched.length - 1" class="no-redirect">{{ item.meta.title }}</span>
|
||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-breadcrumb">
|
||||
import { computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const handleLink = (item) => {
|
||||
router.push({
|
||||
path: item.path,
|
||||
});
|
||||
};
|
||||
|
||||
const matched = computed(() => route.matched.filter((item) => item.meta && item.meta.title && item.meta.breadcrumb !== false));
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.layout-breadcrumb {
|
||||
@include flex-row;
|
||||
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,40 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-26 23:04:29
|
||||
-->
|
||||
<template>
|
||||
<div class="layout-hamburger" @click="handleCollapse">
|
||||
<el-icon v-if="isCollapse" class="icon"><expand /></el-icon>
|
||||
<el-icon v-else class="icon"><fold /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-hamburger">
|
||||
import { computed } from 'vue';
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
|
||||
const SettingStore = useSettingStore();
|
||||
const isCollapse = computed(() => !SettingStore.isCollapse);
|
||||
|
||||
const handleCollapse = () => {
|
||||
SettingStore.setCollapse(isCollapse.value);
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.layout-hamburger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 15px;
|
||||
height: 100%;
|
||||
&:hover {
|
||||
background: rgb(0 0 0 / 2.5%);
|
||||
}
|
||||
.icon {
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,108 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2025-01-24 15:11:22
|
||||
-->
|
||||
<template>
|
||||
<div class="layout-header-placeholder" :style="stylePlaceholder()"></div>
|
||||
<div
|
||||
class="layout-header"
|
||||
:class="{
|
||||
'fixed-header': themeConfig.fixedHeader,
|
||||
collapse: themeConfig.fixedHeader && isCollapse,
|
||||
'no-collapse': themeConfig.fixedHeader && !isCollapse,
|
||||
}"
|
||||
>
|
||||
<div class="layout-header-inner">
|
||||
<div class="layout-header-left">
|
||||
<Hamburger />
|
||||
<Breadcrumb />
|
||||
</div>
|
||||
<div class="layout-header-right">
|
||||
<ScreenFull class="layout-header-tool" />
|
||||
<Avatar class="layout-header-tool" />
|
||||
</div>
|
||||
</div>
|
||||
<TagsView v-if="themeConfig.showTag" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-header">
|
||||
import { computed } from 'vue';
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
import { setPx } from '@/utils';
|
||||
import Hamburger from '../Hamburger';
|
||||
import Breadcrumb from '../Breadcrumb';
|
||||
import ScreenFull from '../ScreenFull';
|
||||
import Avatar from '../Avatar';
|
||||
import TagsView from '../TagsView';
|
||||
|
||||
const SettingStore = useSettingStore();
|
||||
|
||||
// 主题配置
|
||||
const themeConfig = computed(() => SettingStore.themeConfig);
|
||||
const isCollapse = computed(() => !SettingStore.isCollapse);
|
||||
|
||||
const stylePlaceholder = () => {
|
||||
return { height: themeConfig.value.showTag ? setPx(90) : setPx(50) };
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout-header {
|
||||
width: 100%;
|
||||
background: white;
|
||||
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
|
||||
transition: width 0.28s;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
&.fixed-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
}
|
||||
&.collapse {
|
||||
width: calc(100% - 60px);
|
||||
}
|
||||
&.no-collapse {
|
||||
width: calc(100% - 210px);
|
||||
}
|
||||
&-placeholder {
|
||||
height: 50px;
|
||||
}
|
||||
&-inner {
|
||||
@include flex-row;
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 10px 0 0;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
&-left {
|
||||
@include flex-row;
|
||||
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
&-right {
|
||||
@include flex-row;
|
||||
|
||||
align-items: center;
|
||||
}
|
||||
&-tool {
|
||||
margin-right: 10px;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
:deep(.el-icon) {
|
||||
font-size: 20px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,47 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2025-02-13 16:04:43
|
||||
-->
|
||||
<template>
|
||||
<div class="logo">
|
||||
<!-- <img src="/images/logo.png" class="logo-picture" /> -->
|
||||
<h2 v-show="!isCollapse" class="logo-title">{{ VITE_APP_TITLE }}</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="logo">
|
||||
defineProps({
|
||||
isCollapse: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const { VITE_APP_TITLE } = import.meta.env;
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.logo {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
margin-bottom: 2px;
|
||||
padding: 7px 5px;
|
||||
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
|
||||
transition: all 0.28s;
|
||||
@include flex-row;
|
||||
&-picture {
|
||||
margin: 0 auto;
|
||||
width: 70px;
|
||||
height: 35px;
|
||||
}
|
||||
&-title {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,48 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-02-05 15:47:56
|
||||
-->
|
||||
<template>
|
||||
<div class="layout-main">
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition name="fade-slide" mode="out-in" appear>
|
||||
<keep-alive v-if="isReload" :include="cacheRoutes">
|
||||
<component :is="useWrapComponents(Component, route)" :key="route.path" />
|
||||
</keep-alive>
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-main">
|
||||
import { computed } from 'vue';
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
import { usePermissionStore } from '@/store/modules/permission';
|
||||
import { useWrapComponents } from '@/hooks/useWrapComponents';
|
||||
|
||||
const SettingStore = useSettingStore();
|
||||
const PermissionStore = usePermissionStore();
|
||||
const cacheRoutes = computed(() => PermissionStore.keepAliveRoutes);
|
||||
const isReload = computed(() => SettingStore.isReload);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout-main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@include scrollable;
|
||||
|
||||
box-sizing: border-box;
|
||||
&-inner {
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
background-color: #f5f5f5;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2024-01-27 16:02:43
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-04-12 21:12:01
|
||||
-->
|
||||
<template>
|
||||
<el-icon v-if="icon.includes('icon')" :class="`iconfont ${icon}`" :size="size" />
|
||||
<el-icon v-else :size="size"> <component :is="icon" /></el-icon>
|
||||
</template>
|
||||
<script setup name="layout-icon">
|
||||
defineProps({
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 20,
|
||||
},
|
||||
});
|
||||
</script>
|
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-27 09:29:36
|
||||
-->
|
||||
<template>
|
||||
<component :is="type" v-bind="linkProps(to)">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-link">
|
||||
import { computed } from 'vue';
|
||||
import { isExternal } from '@/utils/validate';
|
||||
|
||||
const props = defineProps({
|
||||
to: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const type = computed(() => {
|
||||
if (isExternal(props.to)) {
|
||||
return 'a';
|
||||
}
|
||||
return 'router-link';
|
||||
});
|
||||
|
||||
const linkProps = (to) => {
|
||||
if (isExternal(to)) {
|
||||
return {
|
||||
href: to,
|
||||
target: '_blank',
|
||||
rel: 'noopener',
|
||||
};
|
||||
}
|
||||
return {
|
||||
to: to,
|
||||
};
|
||||
};
|
||||
</script>
|
@ -0,0 +1,81 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-27 16:07:37
|
||||
-->
|
||||
<template>
|
||||
<template v-if="!item.hidden">
|
||||
<template v-if="!item.alwaysShow && hasOneShowingChild(item.children, item)">
|
||||
<layout-link v-if="onlyOneChild.meta" :to="onlyOneChild.path">
|
||||
<el-menu-item :index="onlyOneChild.path">
|
||||
<layout-icon :size="20" :icon="onlyOneChild?.meta?.icon" />
|
||||
<template #title>{{ onlyOneChild.meta && onlyOneChild.meta?.title }}</template>
|
||||
</el-menu-item>
|
||||
</layout-link>
|
||||
</template>
|
||||
<el-sub-menu v-else :index="item.path" teleported>
|
||||
<template #title>
|
||||
<layout-icon :size="20" :icon="item?.meta?.icon" />
|
||||
<span>{{ item.meta && item.meta?.title }}</span>
|
||||
</template>
|
||||
<sub-item v-for="child in item.children" :key="child.path" :item="child" />
|
||||
</el-sub-menu>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup name="sub-item">
|
||||
import { ref } from 'vue';
|
||||
// import { isExternal } from '@/utils/validate.js';
|
||||
import LayoutLink from './Link';
|
||||
import LayoutIcon from './Icon';
|
||||
// import path from 'path-browserify';
|
||||
|
||||
defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
basePath: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const onlyOneChild = ref(null);
|
||||
const hasOneShowingChild = (children = [], parent) => {
|
||||
const showingChildren = children.filter((item) => {
|
||||
// 过滤掉需要隐藏的菜单
|
||||
if (item.hidden) {
|
||||
return false;
|
||||
} else {
|
||||
// 临时设置(如果只有一个显示子项,则将使用)
|
||||
onlyOneChild.value = item;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// 当只有一个子路由器时,默认情况下会显示该子路由器
|
||||
if (showingChildren.length === 1) {
|
||||
return true;
|
||||
}
|
||||
// 如果没有要显示的子路由器,则显示父路由器
|
||||
if (showingChildren.length === 0) {
|
||||
onlyOneChild.value = { ...parent, noShowingChildren: true };
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// const resolvePath = (routePath) => {
|
||||
// if (isExternal(routePath)) {
|
||||
// return routePath;
|
||||
// }
|
||||
// if (isExternal(props.basePath)) {
|
||||
// return props.basePath;
|
||||
// }
|
||||
// return path.resolve(props.basePath, routePath);
|
||||
// };
|
||||
</script>
|
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 14:29:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-01-27 15:54:43
|
||||
-->
|
||||
<template>
|
||||
<div class="layout-screenful">
|
||||
<el-tooltip effect="dark" :content="isFullscreen ? '取消全屏' : '全屏'" placement="bottom">
|
||||
<span @click="handleFullScreen">
|
||||
<el-icon :class="['iconfont', isFullscreen ? 'icon-exit-fullscreen' : 'icon-fullscreen']"></el-icon>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-screenful">
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import screenfull from 'screenfull';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const isFullscreen = ref(false);
|
||||
|
||||
const handleChange = () => {
|
||||
isFullscreen.value = screenfull.isFullscreen;
|
||||
};
|
||||
|
||||
const handleFullScreen = () => {
|
||||
if (!screenfull.isEnabled) {
|
||||
ElMessage.warning('you browser can not work');
|
||||
return false;
|
||||
}
|
||||
screenfull.toggle();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
screenfull.isEnabled && screenfull.on('change', handleChange);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
screenfull.isEnabled && screenfull.off('change', handleChange);
|
||||
});
|
||||
</script>
|
@ -0,0 +1,87 @@
|
||||
<!--
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2024-01-27 20:01:45
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-03-30 14:32:07
|
||||
-->
|
||||
<template>
|
||||
<div class="layout-sider" :class="{ 'has-logo': themeConfig.showLogo }">
|
||||
<Logo v-if="themeConfig.showLogo" :is-collapse="isCollapse" />
|
||||
<el-scrollbar wrap-class="layout-sider-scrollbar">
|
||||
<el-menu
|
||||
class="layout-sider-menu"
|
||||
background-color="#fff"
|
||||
text-color="#333"
|
||||
active-text-color=""
|
||||
:default-active="activeMenu"
|
||||
:unique-opened="SettingStore.themeConfig.uniqueOpened"
|
||||
:collapse-transition="false"
|
||||
:collapse="isCollapse"
|
||||
>
|
||||
<SubItem v-for="item in permissionRoutes" :key="item.path" :item="item" />
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-sider">
|
||||
import { computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import Logo from '../Logo';
|
||||
import SubItem from '../Menu/SubItem';
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
import { usePermissionStore } from '@/store/modules/permission';
|
||||
|
||||
const route = useRoute();
|
||||
const PermissionStore = usePermissionStore();
|
||||
const SettingStore = useSettingStore();
|
||||
|
||||
// 是否折叠
|
||||
const isCollapse = computed(() => !SettingStore.isCollapse);
|
||||
|
||||
// 设置
|
||||
const themeConfig = computed(() => SettingStore.themeConfig);
|
||||
|
||||
// 获取路由
|
||||
const permissionRoutes = computed(() => PermissionStore.permissionRoutes);
|
||||
|
||||
const activeMenu = computed(() => {
|
||||
const { meta, path } = route;
|
||||
if (meta.activeMenu) {
|
||||
return meta.activeMenu;
|
||||
}
|
||||
return path;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout-sider {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 98;
|
||||
overflow: hidden;
|
||||
width: 210px;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
|
||||
transition: width 0.28s;
|
||||
&-scrollbar {
|
||||
height: calc(100vh - 60px) !important;
|
||||
}
|
||||
:deep(.el-scrollbar__wrap) {
|
||||
height: calc(100vh - 60px) !important;
|
||||
}
|
||||
&-menu {
|
||||
border-right: 0;
|
||||
:deep(.el-menu-item.is-active) {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
&:not(.el-menu--collapse) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dropdown trigger="hover">
|
||||
<el-button size="small" type="primary">
|
||||
<span>更多</span>
|
||||
<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="refresh"
|
||||
><el-icon :size="14"><Refresh /></el-icon> 刷新当页</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item @click="closeCurrentTab"
|
||||
><el-icon :size="14"><FolderRemove /></el-icon> 关闭当前</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item @click="closeOtherTab"
|
||||
><el-icon :size="14"><Close /></el-icon>关闭其他</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item @click="closeAllTab"
|
||||
><el-icon :size="14"><FolderDelete /></el-icon>关闭所有</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout-tags-view-more">
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView';
|
||||
|
||||
const route = useRoute();
|
||||
const SettingStore = useSettingStore();
|
||||
const TagsViewStore = useTagsViewStore();
|
||||
const refresh = () => {
|
||||
SettingStore.setReload();
|
||||
};
|
||||
|
||||
// 关闭当前
|
||||
const closeCurrentTab = () => {
|
||||
TagsViewStore.toLastView(route.path);
|
||||
TagsViewStore.delView(route.path);
|
||||
};
|
||||
|
||||
// 关闭其他
|
||||
const closeOtherTab = async () => {
|
||||
TagsViewStore.delOtherViews(route.path);
|
||||
};
|
||||
|
||||
// 关闭所有 去首页
|
||||
const closeAllTab = async () => {
|
||||
await TagsViewStore.delAllViews();
|
||||
TagsViewStore.goHome();
|
||||
};
|
||||
</script>
|
@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div class="layout-tags-view">
|
||||
<div class="layout-tags-view-inner">
|
||||
<el-tabs v-model="activeTabsValue" type="card" @tab-click="tabClick" @tab-remove="removeTab">
|
||||
<el-tab-pane
|
||||
v-for="item in visitedViews"
|
||||
:key="item.path"
|
||||
:path="item.path"
|
||||
:label="item.title"
|
||||
:name="item.path"
|
||||
:closable="!(item.meta && item.meta.affix)"
|
||||
>
|
||||
<template #label>
|
||||
<el-icon v-if="item.icon" class="tabs-icon">
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
{{ item.title }}
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div class="layout-tags-view-more">
|
||||
<MoreButton />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup name="layout-tags-view">
|
||||
import { computed, watch, ref, onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import path from 'path-browserify';
|
||||
import { useTagsViewStore } from '@/store/modules/tagsView';
|
||||
import { usePermissionStore } from '@/store/modules/permission';
|
||||
import MoreButton from './More';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const TagsViewStore = useTagsViewStore();
|
||||
const PermissionStore = usePermissionStore();
|
||||
const visitedViews = computed(() => TagsViewStore.visitedViews);
|
||||
const routes = computed(() => PermissionStore.routes);
|
||||
|
||||
const addTags = () => {
|
||||
const { name } = route;
|
||||
if (name === 'Login') {
|
||||
return;
|
||||
}
|
||||
if (name) {
|
||||
TagsViewStore.addView(route);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
let affixTags = ref([]);
|
||||
function filterAffixTags(routes, basePath = '/') {
|
||||
let tags = [];
|
||||
routes.forEach((route) => {
|
||||
if (route.meta && route.meta.affix) {
|
||||
const tagPath = path.resolve(basePath, route.path);
|
||||
tags.push({
|
||||
fullPath: tagPath,
|
||||
path: tagPath,
|
||||
name: route.name,
|
||||
meta: { ...route.meta },
|
||||
});
|
||||
}
|
||||
if (route.children) {
|
||||
const tempTags = filterAffixTags(route.children, route.path);
|
||||
if (tempTags.length >= 1) {
|
||||
tags = [...tags, ...tempTags];
|
||||
}
|
||||
}
|
||||
});
|
||||
return tags;
|
||||
}
|
||||
const initTags = () => {
|
||||
let routesNew = routes.value;
|
||||
let affixTag = (affixTags.value = filterAffixTags(routesNew));
|
||||
for (const tag of affixTag) {
|
||||
if (tag.name) {
|
||||
TagsViewStore.addVisitedView(tag);
|
||||
}
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
initTags();
|
||||
addTags();
|
||||
});
|
||||
watch(route, () => {
|
||||
addTags();
|
||||
});
|
||||
|
||||
const activeTabsValue = computed({
|
||||
get: () => {
|
||||
return TagsViewStore.activeTabsValue;
|
||||
},
|
||||
set: (val) => {
|
||||
TagsViewStore.setTabsMenuValue(val);
|
||||
},
|
||||
});
|
||||
|
||||
function toLastView(activeTabPath) {
|
||||
let index = visitedViews.value.findIndex((item) => item.path === activeTabPath);
|
||||
const nextTab = visitedViews.value[index + 1] || visitedViews.value[index - 1];
|
||||
if (!nextTab) return;
|
||||
router.push(nextTab.path);
|
||||
TagsViewStore.addVisitedView(nextTab);
|
||||
}
|
||||
|
||||
const tabClick = (tabItem) => {
|
||||
let path = tabItem.props.name;
|
||||
router.push(path);
|
||||
};
|
||||
|
||||
const isActive = (path) => {
|
||||
return path === route.path;
|
||||
};
|
||||
|
||||
const removeTab = async (activeTabPath) => {
|
||||
if (isActive(activeTabPath)) {
|
||||
toLastView(activeTabPath);
|
||||
}
|
||||
await TagsViewStore.delView(activeTabPath);
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.layout-tags-view {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
background: white;
|
||||
&-inner {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
.el-tabs--card :deep(.el-tabs__header) {
|
||||
margin: 0;
|
||||
padding: 0 10px;
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:deep(.el-tabs) {
|
||||
.el-tabs__nav {
|
||||
border: none;
|
||||
}
|
||||
.el-tabs__header .el-tabs__item {
|
||||
border: none;
|
||||
color: #cccccc;
|
||||
}
|
||||
.el-tabs__header .el-tabs__item.is-active {
|
||||
border-bottom: 2px solid $color-primary;
|
||||
color: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-more {
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
54
sub-government-screen-service/src/layouts/index.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<!--
|
||||
* @Description: layout
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2024-01-26 20:13:37
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-02-05 16:03:31
|
||||
-->
|
||||
<template>
|
||||
<div
|
||||
class="basic-layout"
|
||||
:class="{
|
||||
hideSider: !SettingStore.isCollapse,
|
||||
}"
|
||||
>
|
||||
<Sider />
|
||||
<div class="basic-layout-container">
|
||||
<Header />
|
||||
<Main />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="layout">
|
||||
import { useSettingStore } from '@/store/modules/setting';
|
||||
|
||||
import Sider from './component/Sider';
|
||||
import Header from './component/Header';
|
||||
import Main from './component/Main';
|
||||
const SettingStore = useSettingStore();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.basic-layout {
|
||||
width: 100%;
|
||||
min-width: 1200px;
|
||||
height: 100%;
|
||||
&.hideSider {
|
||||
:deep(.layout-sider) {
|
||||
width: 60px !important;
|
||||
}
|
||||
.basic-layout-container {
|
||||
margin-left: 60px !important;
|
||||
}
|
||||
}
|
||||
&-container {
|
||||
position: relative;
|
||||
margin-left: 210px;
|
||||
height: 100%;
|
||||
transition: margin-left 0.28s;
|
||||
box-sizing: border-box;
|
||||
@include flex-column;
|
||||
}
|
||||
}
|
||||
</style>
|
30
sub-government-screen-service/src/main.js
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2024-01-24 17:14:41
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2024-03-22 10:11:34
|
||||
*/
|
||||
import 'virtual:svg-icons-register';
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import pinia from './store';
|
||||
import ElementPlus from 'element-plus';
|
||||
import 'element-plus/dist/index.css';
|
||||
import Avue from '@smallwei/avue';
|
||||
import '@smallwei/avue/lib/index.css';
|
||||
import './utils/permission';
|
||||
import { registerDirective } from './directives';
|
||||
import { registerGlobalComponents } from './plugins/globalComponents';
|
||||
import { registerElIcons } from './plugins/icon';
|
||||
import { registerMicroApps } from './plugins/micro';
|
||||
|
||||
const app = createApp(App);
|
||||
// 注册 Vue3 Scroll Seamless 组件
|
||||
// app.component('Vue3ScrollSeamless', vue3ScrollSeamless);
|
||||
app.use(pinia).use(router).use(ElementPlus).use(Avue);
|
||||
registerGlobalComponents(app);
|
||||
registerElIcons(app);
|
||||
registerDirective(app);
|
||||
registerMicroApps(app);
|
@ -0,0 +1,8 @@
|
||||
import * as components from '#/components';
|
||||
|
||||
// 全局注册组件
|
||||
export const registerGlobalComponents = (app) => {
|
||||
Object.keys(components).forEach((key) => {
|
||||
app.component(key, components[key]);
|
||||
});
|
||||
};
|
8
sub-government-screen-service/src/plugins/icon.js
Normal file
@ -0,0 +1,8 @@
|
||||
import * as ElIconsModules from '@element-plus/icons-vue';
|
||||
|
||||
// 全局注册element-plus icon图标组件
|
||||
export const registerElIcons = (app) => {
|
||||
Object.keys(ElIconsModules).forEach((key) => {
|
||||
app.component(key, ElIconsModules[key]);
|
||||
});
|
||||
};
|
26
sub-government-screen-service/src/plugins/micro.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
|
||||
|
||||
export const registerMicroApps = async (app) => {
|
||||
const initQiankun = () => {
|
||||
renderWithQiankun({
|
||||
bootstrap() {
|
||||
console.log('bootstrap');
|
||||
},
|
||||
mount(props) {
|
||||
console.log('mount', props);
|
||||
render(props);
|
||||
},
|
||||
update(props) {
|
||||
console.log('update', props);
|
||||
},
|
||||
unmount(props) {
|
||||
console.log('unmount', props);
|
||||
},
|
||||
});
|
||||
};
|
||||
const render = async ({ container }) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
app.mount(container ? container.querySelector('#app') : '#app');
|
||||
};
|
||||
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQiankun() : render({});
|
||||
};
|
87
sub-government-screen-service/src/router/index.js
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* @Description: router
|
||||
* @Author: zenghua.wang
|
||||
* @Date: 2023-06-20 11:48:41
|
||||
* @LastEditors: zenghua.wang
|
||||
* @LastEditTime: 2025-03-11 16:51:49
|
||||
*/
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import Layout from '@/layouts/index.vue';
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/sub-government-screen-service/404',
|
||||
name: '404',
|
||||
component: () => import('@/views/error/404.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/403',
|
||||
name: '403',
|
||||
component: () => import('@/views/error/403.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/home',
|
||||
name: 'home',
|
||||
component: () => import('@/views/home/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/land',
|
||||
name: 'land',
|
||||
component: () => import('@/views/land/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/inputs',
|
||||
name: 'inputs',
|
||||
component: () => import('@/views/inputs/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/entities',
|
||||
name: 'entities',
|
||||
component: () => import('@/views/entities/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/breed',
|
||||
name: 'breed',
|
||||
component: () => import('@/views/breed/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/plant',
|
||||
name: 'plant',
|
||||
component: () => import('@/views/plant/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/trace',
|
||||
name: 'trace',
|
||||
component: () => import('@/views/trace/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: '/sub-government-screen-service/early',
|
||||
name: 'early',
|
||||
component: () => import('@/views/early/index.vue'),
|
||||
hidden: true,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @Title notFoundRouter(找不到路由)
|
||||
*/
|
||||
export const notFoundRouter = {
|
||||
path: '/sub-government-screen-service/:pathMatch(.*)',
|
||||
name: 'notFound',
|
||||
redirect: '/sub-government-screen-service/404',
|
||||
};
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: constantRoutes,
|
||||
});
|
||||
|
||||
export default router;
|
20
sub-government-screen-service/src/store/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { defineStore, createPinia } from 'pinia';
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
|
||||
|
||||
const { VITE_APP_NAME } = import.meta.env;
|
||||
|
||||
export const Store = defineStore({
|
||||
id: VITE_APP_NAME,
|
||||
state: () => ({}),
|
||||
getters: {},
|
||||
actions: {},
|
||||
persist: {
|
||||
key: VITE_APP_NAME,
|
||||
storage: window.sessionStorage,
|
||||
},
|
||||
});
|
||||
|
||||
const pinia = createPinia();
|
||||
pinia.use(piniaPluginPersistedstate);
|
||||
|
||||
export default pinia;
|
@ -0,0 +1,53 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { constantRoutes, notFoundRouter } from '@/router';
|
||||
import { createAsyncRoutes, filterAsyncRoutes, filterKeepAlive } from '@/utils/router';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { getTree } from '@/utils';
|
||||
import { GenKey } from '@/config';
|
||||
|
||||
export const usePermissionStore = defineStore({
|
||||
id: GenKey('permissionStore'),
|
||||
state: () => ({
|
||||
// 路由
|
||||
routes: [],
|
||||
// 动态路由
|
||||
asyncRoutes: [],
|
||||
// 缓存路由
|
||||
cacheRoutes: {},
|
||||
}),
|
||||
getters: {
|
||||
permissionRoutes: (state) => {
|
||||
return state.routes;
|
||||
},
|
||||
keepAliveRoutes: (state) => {
|
||||
return filterKeepAlive(state.asyncRoutes);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
generateRoutes(roles) {
|
||||
return new Promise((resolve) => {
|
||||
// 在这判断是否有权限,哪些角色拥有哪些权限
|
||||
const UserStore = useUserStore();
|
||||
this.asyncRoutes = createAsyncRoutes(getTree(UserStore.getMenus()));
|
||||
let accessedRoutes;
|
||||
if (roles && roles.length && !roles.includes('admin')) {
|
||||
accessedRoutes = filterAsyncRoutes(this.asyncRoutes, roles);
|
||||
} else {
|
||||
accessedRoutes = this.asyncRoutes || [];
|
||||
}
|
||||
accessedRoutes = accessedRoutes.concat(notFoundRouter);
|
||||
this.routes = constantRoutes.concat(accessedRoutes);
|
||||
resolve(accessedRoutes);
|
||||
});
|
||||
},
|
||||
clearRoutes() {
|
||||
this.routes = [];
|
||||
this.asyncRoutes = [];
|
||||
this.cacheRoutes = [];
|
||||
},
|
||||
getCacheRoutes() {
|
||||
this.cacheRoutes = filterKeepAlive(this.asyncRoutes);
|
||||
return this.cacheRoutes;
|
||||
},
|
||||
},
|
||||
});
|
70
sub-government-screen-service/src/store/modules/setting.js
Normal file
@ -0,0 +1,70 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { CONSTANTS } from '@/config';
|
||||
import { GenKey } from '@/config';
|
||||
|
||||
export const useSettingStore = defineStore({
|
||||
id: GenKey('settingStore'),
|
||||
state: () => ({
|
||||
// menu 是否收缩
|
||||
isCollapse: true,
|
||||
//
|
||||
withoutAnimation: false,
|
||||
device: 'desktop',
|
||||
// 刷新当前页
|
||||
isReload: true,
|
||||
// 主题设置
|
||||
themeConfig: {
|
||||
// 显示设置
|
||||
showSetting: false,
|
||||
// 菜单展示模式 默认 vertical horizontal / vertical /columns
|
||||
mode: 'vertical',
|
||||
// tagsView 是否展示 默认展示
|
||||
showTag: true,
|
||||
// 页脚
|
||||
footer: true,
|
||||
// 深色模式 切换暗黑模式
|
||||
isDark: false,
|
||||
// 显示侧边栏Logo
|
||||
showLogo: true,
|
||||
// 主题颜色
|
||||
primary: CONSTANTS.PRIMARY,
|
||||
// element组件大小
|
||||
globalComSize: 'default',
|
||||
// 是否只保持一个子菜单的展开
|
||||
uniqueOpened: true,
|
||||
// 固定header
|
||||
fixedHeader: true,
|
||||
// 灰色模式
|
||||
gray: false,
|
||||
// 色弱模式
|
||||
weak: false,
|
||||
},
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
// 设置主题
|
||||
setThemeConfig({ key, val }) {
|
||||
this.themeConfig[key] = val;
|
||||
},
|
||||
// 切换 Collapse
|
||||
setCollapse(value) {
|
||||
this.isCollapse = value;
|
||||
this.withoutAnimation = false;
|
||||
},
|
||||
// 关闭侧边栏
|
||||
closeSideBar({ withoutAnimation }) {
|
||||
this.isCollapse = false;
|
||||
this.withoutAnimation = withoutAnimation;
|
||||
},
|
||||
toggleDevice(device) {
|
||||
this.device = device;
|
||||
},
|
||||
// 刷新
|
||||
setReload() {
|
||||
this.isReload = false;
|
||||
setTimeout(() => {
|
||||
this.isReload = true;
|
||||
}, 50);
|
||||
},
|
||||
},
|
||||
});
|
105
sub-government-screen-service/src/store/modules/tagsView.js
Normal file
@ -0,0 +1,105 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { GenKey } from '@/config';
|
||||
import router from '@/router';
|
||||
|
||||
export const useTagsViewStore = defineStore({
|
||||
id: GenKey('tagsViewStore'),
|
||||
state: () => ({
|
||||
activeTabsValue: '/home',
|
||||
visitedViews: [],
|
||||
cachedViews: [],
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setTabsMenuValue(val) {
|
||||
this.activeTabsValue = val;
|
||||
},
|
||||
addView(view) {
|
||||
this.addVisitedView(view);
|
||||
},
|
||||
removeView(routes) {
|
||||
return new Promise((resolve) => {
|
||||
this.visitedViews = this.visitedViews.filter((item) => !routes.includes(item.path));
|
||||
resolve(null);
|
||||
});
|
||||
},
|
||||
addVisitedView(view) {
|
||||
this.setTabsMenuValue(view.path);
|
||||
if (this.visitedViews.some((v) => v.path === view.path)) return;
|
||||
|
||||
this.visitedViews.push(
|
||||
Object.assign({}, view, {
|
||||
title: view.meta.title || 'no-name',
|
||||
})
|
||||
);
|
||||
if (view.meta.keepAlive) {
|
||||
this.cachedViews.push(view.name);
|
||||
}
|
||||
},
|
||||
delView(activeTabPath) {
|
||||
return new Promise((resolve) => {
|
||||
this.delVisitedView(activeTabPath);
|
||||
this.delCachedView(activeTabPath);
|
||||
resolve({
|
||||
visitedViews: [...this.visitedViews],
|
||||
cachedViews: [...this.cachedViews],
|
||||
});
|
||||
});
|
||||
},
|
||||
toLastView(activeTabPath) {
|
||||
const index = this.visitedViews.findIndex((item) => item.path === activeTabPath);
|
||||
const nextTab = this.visitedViews[index + 1] || this.visitedViews[index - 1];
|
||||
if (!nextTab) return;
|
||||
router.push(nextTab.path);
|
||||
this.addVisitedView(nextTab);
|
||||
},
|
||||
delVisitedView(path) {
|
||||
return new Promise((resolve) => {
|
||||
this.visitedViews = this.visitedViews.filter((v) => {
|
||||
return v.path !== path || v.meta.affix;
|
||||
});
|
||||
this.cachedViews = this.cachedViews.filter((v) => {
|
||||
return v.path !== path || v.meta.affix;
|
||||
});
|
||||
resolve([...this.visitedViews]);
|
||||
});
|
||||
},
|
||||
delCachedView(view) {
|
||||
return new Promise((resolve) => {
|
||||
const index = this.cachedViews.indexOf(view.name);
|
||||
index > -1 && this.cachedViews.splice(index, 1);
|
||||
resolve([...this.cachedViews]);
|
||||
});
|
||||
},
|
||||
clearVisitedView() {
|
||||
this.delAllViews();
|
||||
},
|
||||
delAllViews() {
|
||||
return new Promise((resolve) => {
|
||||
this.visitedViews = this.visitedViews.filter((v) => v.meta.affix);
|
||||
this.cachedViews = this.visitedViews.filter((v) => v.meta.affix);
|
||||
resolve([...this.visitedViews]);
|
||||
});
|
||||
},
|
||||
delOtherViews(path) {
|
||||
this.visitedViews = this.visitedViews.filter((item) => {
|
||||
return item.path === path || item.meta.affix;
|
||||
});
|
||||
this.cachedViews = this.visitedViews.filter((item) => {
|
||||
return item.path === path || item.meta.affix;
|
||||
});
|
||||
},
|
||||
goHome() {
|
||||
this.activeTabsValue = '/home';
|
||||
router.push({ path: '/home' });
|
||||
},
|
||||
updateVisitedView(view) {
|
||||
for (let v of this.visitedViews) {
|
||||
if (v.path === view.path) {
|
||||
v = Object.assign(v, view);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
65
sub-government-screen-service/src/store/modules/user.js
Normal file
@ -0,0 +1,65 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { GenKey } from '@/config';
|
||||
import { isEmpty, encode, decode } from '@/utils';
|
||||
|
||||
export const useUserStore = defineStore({
|
||||
id: GenKey('userStore'),
|
||||
state: () => ({
|
||||
token: null,
|
||||
userInfo: {},
|
||||
currentOrg: null,
|
||||
orgList: [],
|
||||
menus: [],
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
setToken(token) {
|
||||
this.token = token;
|
||||
},
|
||||
hasToken() {
|
||||
return !isEmpty(this.token);
|
||||
},
|
||||
setUserInfo(userInfo) {
|
||||
this.userInfo = encode(JSON.stringify(userInfo), true);
|
||||
},
|
||||
getUserInfo() {
|
||||
return !isEmpty(this.userInfo) ? JSON.parse(decode(this.userInfo, true)) : {};
|
||||
},
|
||||
setOrgList(orgList) {
|
||||
this.orgList = encode(JSON.stringify(orgList), true);
|
||||
},
|
||||
getOrgList() {
|
||||
return !isEmpty(this.orgList) ? JSON.parse(decode(this.orgList, true)) : [];
|
||||
},
|
||||
setCurrentOrg(org) {
|
||||
this.currentOrg = org;
|
||||
},
|
||||
getCurrentOrg() {
|
||||
const list = this.getOrgList().filter((item) => {
|
||||
return item.id === this.currentOrg;
|
||||
});
|
||||
return !isEmpty(list) ? list[0] : {};
|
||||
},
|
||||
setMenus(menus) {
|
||||
this.menus = encode(JSON.stringify(menus), true);
|
||||
},
|
||||
getMenus() {
|
||||
return !isEmpty(this.menus) ? JSON.parse(decode(this.menus, true)) : [];
|
||||
},
|
||||
logout() {
|
||||
this.token = null;
|
||||
this.userInfo = {};
|
||||
this.currentOrg = null;
|
||||
this.orgList = [];
|
||||
this.menus = [];
|
||||
localStorage.removeItem(GenKey('userStore'));
|
||||
},
|
||||
clear() {
|
||||
localStorage.removeItem(GenKey('userStore'));
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
key: GenKey('userStore'),
|
||||
storage: window.localStorage,
|
||||
},
|
||||
});
|