17 Commits

Author SHA1 Message Date
af3442f276 保存进度! 2025-10-31 19:08:12 +08:00
390a5efbb8 编写上传界面 2025-10-30 18:19:51 +08:00
72a4895328 保存进度! 2025-10-30 16:02:54 +08:00
ef3b31c9e4 编写制度管理。 2025-10-28 23:51:14 +08:00
a11c6ada3d 编写制度文件管理view 2025-10-24 18:07:49 +08:00
ad3320779c 保存进度! 2025-10-24 11:45:27 +08:00
96efb0cf53 保存进度! 2025-10-24 11:45:10 +08:00
44f26dd330 保存进度 2025-10-24 00:36:24 +08:00
7ea8e7ab4d 编写路由代码。 2025-10-23 17:52:01 +08:00
fd4275c3a5 保存进度! 2025-10-22 18:17:36 +08:00
51f96ed6c1 保存进度! 2025-10-17 18:16:51 +08:00
8cc2f8759d 保存进度! 2025-10-16 18:16:46 +08:00
4a79a080c5 更新 README.md 2025-10-16 07:44:55 +00:00
9699e39ecf 保存进度! 2025-10-16 15:43:26 +08:00
c22779bd6a 保存进度! 2025-10-16 15:42:00 +08:00
07bf0e3450 保存进度! 2025-10-16 15:41:29 +08:00
bb25a5db61 保存进度! 2025-10-16 15:40:25 +08:00
57 changed files with 3167 additions and 268 deletions

0
7788.md Normal file
View File

View File

@@ -1,3 +1,9 @@
# regulatory-management-system <h1 style="text-align:center; font-size:2rem;" title>产险厦门分公司规章制度管理工具</h1>
产险厦门分公司规章制度管理工具。 # 概述
产险厦门分公司规章制度管理工具。
# 密码
## mysql
root@localhost ^QaKwfmo#HNy&0D7

View File

@@ -21,8 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.bind.annotation.RequestMethod;
// @SuppressWarnings( "unused" ) // @SuppressWarnings( "unused" )
@Controller @Controller
@@ -36,6 +34,7 @@ public class FileUpload
* 3、MultipartFile参数形参名称必须和请求form中file标签的name属性一致否则值为null。 * 3、MultipartFile参数形参名称必须和请求form中file标签的name属性一致否则值为null。
* 4、返回值为接收结果和文件保存绝对路径。 * 4、返回值为接收结果和文件保存绝对路径。
* *
* @deprecated
* @param taskName 任务名称字符串 * @param taskName 任务名称字符串
* @param files MultipartFile结构的文件对象 * @param files MultipartFile结构的文件对象
* @param request HttpServletRequest对象实例 * @param request HttpServletRequest对象实例
@@ -43,62 +42,73 @@ public class FileUpload
*/ */
// @RequestMapping( path = "/file-upload.do" ) // @RequestMapping( path = "/file-upload.do" )
// @ResponseBody // @ResponseBody
public FileUploadResult getUploadFile( // public FileUploadResult getUploadFile(
@RequestParam( "task-name" ) String taskName, // @RequestParam( "task-name" ) String taskName,
@RequestParam( "files" ) MultipartFile file, // @RequestParam( "files" ) MultipartFile file,
HttpServletRequest request // HttpServletRequest request
) // )
{ // {
// session id用来创建临时目录避免重复 // // session id用来创建临时目录避免重复
String sessionID = request.getSession().getId(); // String sessionID = request.getSession().getId();
FileUploadResult result = new FileUploadResult(); // FileUploadResult result = new FileUploadResult();
Vector<String> fileNames = new Vector<String>(); // Vector<String> fileNames = new Vector<String>();
result.setSuccess( true ); // result.setSuccess( true );
result.setMessage( "上传成功!" ); // result.setMessage( "上传成功!" );
String filePath = request.getServletContext().getRealPath( "/temp/upload/" + sessionID ); // String filePath = request.getServletContext().getRealPath( "/temp/upload/" + sessionID );
File dir = new File( filePath ); // File dir = new File( filePath );
if ( !dir.mkdirs() ) // if ( !dir.mkdirs() )
{ // {
} // }
// 检查文件长度如果为0则跳过 // // 检查文件长度如果为0则跳过
if ( file.isEmpty() ) // if ( file.isEmpty() )
{ // {
result.setSuccess( false ); // result.setSuccess( false );
result.setMessage( "不允许上传空文件。" ); // result.setMessage( "不允许上传空文件。" );
} // }
else // else
{ // {
// 保存文件到临时目录 // // 保存文件到临时目录
Long milliSecond = LocalDateTime.now().toInstant( ZoneOffset.of( "+8" ) ).toEpochMilli(); // Long milliSecond = LocalDateTime.now().toInstant( ZoneOffset.of( "+8" ) ).toEpochMilli();
String fileName = String.valueOf( milliSecond ) + file.getOriginalFilename(); // String fileName = String.valueOf( milliSecond ) + file.getOriginalFilename();
File destFile = new File( filePath, fileName ); // File destFile = new File( filePath, fileName );
// String fileName = file.getOriginalFilename(); // // String fileName = file.getOriginalFilename();
try // try
{ // {
file.transferTo( destFile ); // file.transferTo( destFile );
// 把上传文件的绝对路径保存,返回给前端 // // 把上传文件的绝对路径保存,返回给前端
fileNames.add( destFile.getAbsolutePath() ); // fileNames.add( destFile.getAbsolutePath() );
result.setSuccess( true ); // result.setSuccess( true );
result.setMessage( "上传成功" ); // result.setMessage( "上传成功" );
result.setFileList( fileNames ); // result.setFileList( fileNames );
} // }
catch ( IOException error ) // catch ( IOException error )
{ // {
result.setSuccess( false ); // result.setSuccess( false );
result.setMessage( "上传失败,原因:" + error.getMessage() ); // result.setMessage( "上传失败,原因:" + error.getMessage() );
} // }
} // }
return result; // return result;
} // }
/**
* 接收上传文件,并保存到临时目录:
* 1、临时目录下再用sessionID作为子目录保存文件。
* 2、保存时不更改文件名会覆盖同名文件。
* 3、MultipartFile参数形参名称必须和请求form中file标签的name属性一致否则值为null。
* 4、返回值为接收结果和文件保存绝对路径。
* @param fileName
* @param file
* @param request
* @return
*/
@RequestMapping( path = "/file-upload.do" ) @RequestMapping( path = "/file-upload.do" )
@ResponseBody @ResponseBody
public FileUploadResult saveUploadFile( public FileUploadResult saveUploadFile(

View File

@@ -38,7 +38,7 @@ public class FileUploadResult extends QueryResponse
public FileUploadResult( public FileUploadResult(
boolean success, boolean success,
String message, String message,
Vector<String> fileList Vector<UploadedFile> fileList
) )
{ {
super( success, message ); super( success, message );
@@ -46,17 +46,17 @@ public class FileUploadResult extends QueryResponse
this.fileList = fileList; this.fileList = fileList;
} }
public Vector<String> getFileList() public Vector<UploadedFile> getFileList()
{ {
return fileList; return fileList;
} }
public void setFileList( Vector<String> fileList ) public void setFileList( Vector<UploadedFile> fileList )
{ {
this.fileList = fileList; this.fileList = fileList;
} }
@JsonProperty( "fileList" ) @JsonProperty( "fileList" )
private Vector<String> fileList; private Vector<UploadedFile> fileList;
} }

View File

@@ -0,0 +1,44 @@
/**
* @Author: Kane Wang <wangkane@qq.com>
* @Date: 2025-10-31 17:33:13
* @LastEditors: Kane Wang
* @LastModified: 2025-10-31 17:36:03
* @FilePath: src/main/java/com/cpic/xim/web/controllers/fileupload/UploadedFile.java
* @Description:
*
* Copyright (c) 2025 by Kane All rights reserved
*/
package com.cpic.xim.web.controllers.fileupload;
public class UploadedFile
{
private String fileName;
private String localFilePath;
public String getFileName()
{
return fileName;
}
public void setFileName( String fileName )
{
this.fileName = fileName;
}
public String getLocalFilePath()
{
return localFilePath;
}
public void setLocalFilePath( String localFilePath )
{
this.localFilePath = localFilePath;
}
public UploadedFile( String fileName, String localFilePath )
{
this.fileName = fileName;
this.localFilePath = localFilePath;
}
}

4
code/db/操作.txt Normal file
View File

@@ -0,0 +1,4 @@
alter user 'root'@localhost identified by '^QaKwfmo#HNy&0D7';
create user 'zhiduguanli'@'%' identified by 'Kane@1981';
regulatory_management.*
grant all privileges on regulatory_management.* to 'zhiduguanli'@'%';

156
code/tomcat/server.xml Normal file
View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!-- OpenSSL support using Tomcat Native -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" />
<!-- OpenSSL support using FFM API from Java 22 -->
<!-- <Listener className="org.apache.catalina.core.OpenSSLLifecycleListener" /> -->
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!--The
connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
HTTP Connector: /docs/config/http.html
AJP Connector: /docs/config/ajp.html
Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the NIO implementation. The default
SSLImplementation will depend on the presence of the APR/native
library and the useOpenSSL attribute of the AprLifecycleListener.
Either JSSE or OpenSSL style configuration may be used regardless of
the SSLImplementation selected. JSSE style configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
certificateKeystorePassword="changeit" type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!--
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
-->
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!--For
clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" />
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/regulatory" docBase="D:/数据/制度库/文件" debug="0" privileged="true" />
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>

View File

@@ -123,7 +123,7 @@ module.exports = {
// "@typescript-eslint/indent": ["warn", 4,], // "@typescript-eslint/indent": ["warn", 4,],
"@stylistic/indent": ["warn", 4,], "@stylistic/indent": ["warn", 4,],
"@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unsafe-argument": "warn", // "@typescript-eslint/no-unsafe-argument": "warn",
"@typescript-eslint/no-extra-semi": "off", "@typescript-eslint/no-extra-semi": "off",
"@typescript-eslint/no-inferrable-types": "off", "@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-unused-vars": "warn",
@@ -171,7 +171,7 @@ module.exports = {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off", "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unsafe-argument": "warn", // "@typescript-eslint/no-unsafe-argument": "warn",
// "@typescript-eslint/indent": ["error", 4,], // "@typescript-eslint/indent": ["error", 4,],
"@stylistic/indent": ["warn", 4,], "@stylistic/indent": ["warn", 4,],
"@typescript-eslint/no-extra-semi": "off", "@typescript-eslint/no-extra-semi": "off",

File diff suppressed because it is too large Load Diff

View File

@@ -9,21 +9,32 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"scss": "^0.2.4",
"vue": "^3.5.22", "vue": "^3.5.22",
"vue-router": "^4.5.1" "vue-router": "^4.6.3"
}, },
"devDependencies": { "devDependencies": {
"@stylistic/eslint-plugin": "^5.4.0", "@element-plus/icons-vue": "^2.3.2",
"@typescript-eslint/eslint-plugin": "^8.46.0", "@stylistic/eslint-plugin": "^5.5.0",
"@typescript-eslint/parser": "^8.46.0", "@types/node": "^24.9.2",
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/parser": "^8.46.2",
"@vitejs/plugin-vue": "^6.0.1", "@vitejs/plugin-vue": "^6.0.1",
"@vue-office/docx": "^1.6.3",
"@vue-office/excel": "^1.7.14",
"@vue-office/pdf": "^2.0.10",
"@vue/tsconfig": "^0.8.1", "@vue/tsconfig": "^0.8.1",
"element-plus": "^2.11.4", "axios": "^1.13.1",
"eslint": "^9.37.0", "element-plus": "^2.11.5",
"eslint-plugin-vue": "^10.5.0", "eslint": "^9.38.0",
"eslint-plugin-vue": "^10.5.1",
"path": "^0.12.7",
"sass": "^1.93.2",
"typescript": "~5.9.3", "typescript": "~5.9.3",
"vite": "^7.1.9", "vite": "^7.1.12",
"vue-demi": "^0.14.10",
"vue-eslint-parser": "^10.2.0", "vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.1.1" "vue-pdf-embed": "^2.1.3",
"vue-tsc": "^3.1.2"
} }
} }

View File

@@ -0,0 +1,17 @@
/*
* @Author: Kane
* @Date: 2023-03-04 17:23:02
* @LastEditors: Kane
* @FilePath: /task_schedule/shims-vue.d.ts
* @Description:
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
*/
declare module "*.vue"
{
import { type ComponentOptions } from "vue";
const componentOptions: ComponentOptions;
// export default componentOptions;
}
// declare module "./src/router/index.js";

View File

@@ -0,0 +1,14 @@
/*
* @Author: Kane
* @Date: 2023-03-03 09:56:05
* @LastEditors: Kane
* @FilePath: /task_schedule/src/assets/css/index.scss
* @Description: 全局css的入口文件
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
*/
@import url("./public/reset.scss");
@import url("./public/normalize.scss");
@import url("./public/mixin.scss");
@import url("../font/fonts.css");
// @import url("./public/color.scss");

View File

@@ -0,0 +1,56 @@
/*
* @Author: Kane
* @Date: 2023-02-24 09:36:08
* @LastEditors: Kane
* @LastEditTime: 2023-06-15 15:50:00
* @FilePath: /task_schedule/src/assets/css/public/_public.scss
* @Description: 公共变量
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
*/
//背景色
$wrap-bg-color:#fff;
$span-font-color:#5f5f5f;
//阴影
$box-shadow:0px 0px 20px -10px rgb(14 18 22 / 25%);
$box-shadow-hover:0px 0px 20px -10px rgb(14 18 22 / 50%);
//文字大小
$font-size-normal:14px;
//查询框
@mixin query-box-wrap {
padding: 0px 10px;
span {
font-weight: normal;
display: block;
text-align: right;
font-size: $font-size-normal;
color: $span-font-color;
}
:deep(.el-row) {
display: flex;
align-items: center;
justify-content: left;
}
.el-row+.el-row {
margin-top: 10px;
}
.button-wrapper-right {
display: flex;
justify-content: right;
align-items: center;
}
.button-wrapper-left {
display: flex;
justify-content: left;
align-items: center;
}
}

View File

@@ -0,0 +1,21 @@
/*
* @Author: Kane
* @Date: 2023-02-28 19:25:30
* @LastEditors: Kane
* @FilePath: /task_schedule/src/assets/css/public/global.scss
* @Description:
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
*/
@mixin no-select {
-webkit-touch-callout: none;
-moz-user-select: none;
/*火狐*/
-webkit-user-select: none;
/*webkit浏览器*/
-ms-user-select: none;
/*IE10*/
-khtml-user-select: none;
/*早期浏览器*/
user-select: none;
}

View File

@@ -0,0 +1,389 @@
/*
* @Author: Kane
* @Date: 2023-03-03 10:17:59
* @LastEditors: Kane
* @FilePath: /task_schedule/src/assets/css/public/normalize.scss
* @Description:
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
*/
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
text-size-adjust: 100%;
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box;
/* 1 */
height: 0;
/* 1 */
overflow: visible;
/* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none;
/* 1 */
text-decoration: underline;
/* 2 */
text-decoration: underline dotted;
/* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-size: 100%;
/* 1 */
line-height: 1.15;
/* 1 */
margin: 0;
/* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box;
/* 1 */
color: inherit;
/* 2 */
display: table;
/* 1 */
max-width: 100%;
/* 1 */
padding: 0;
/* 3 */
white-space: normal;
/* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
/* 1 */
padding: 0;
/* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

View File

@@ -0,0 +1,48 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@@ -0,0 +1,31 @@
/*
* @Author: Kane
* @Date: 2023-02-28 19:25:30
* @LastEditors: Kane
* @FilePath: /task_schedule/src/assets/css/public/variables.scss
* @Description:
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
*/
// color
/*
$color-bg-01: #fecb96;
$color-bg-02: #f7954e;
$color-bg-03: #f27620;
$color-bg-04: #da3703;
$color-bg-05: #ba1800;
*/
$color-bg-01: #00b2f8;
$color-bg-02: #00b0fb;
$color-bg-03: #0279ea;
$color-bg-04: #046ed6;
$color-bg-05: #033eb6;
$color-title-font: #046ed6;
$color-charts-bg: #ffffff9f;
$color-honorlist-bg: rgba(255, 255, 255, 0.3);
$banner-background-color: #1d74b2;

View File

@@ -0,0 +1,11 @@
@font-face {
font-family: "FZ-ZHUOHEI";
src: url("FZZhuoHJW.TTF");
font-weight: normal;
}
@font-face {
font-family: "FZ-RGAQSAY";
src: url("FZSJ-RUGAQSAY.TTF");
font-weight: normal;
}

View File

@@ -0,0 +1,86 @@
<!--
* @Author: Kane
* @Date: 2023-03-23 15:07:31
* @LastEditors: Kane
* @FilePath: /task_schedule/src/layout/Index.vue
* @Description:
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
-->
<template>
<el-container class="layout-container">
<el-header class="layout-header">
<LayoutHeader />
</el-header>
<el-container class="layout-container-down">
<el-aside class="layout-aside">
<LayoutAside />
</el-aside>
<el-main class="layout-main">
<LayoutMain />
</el-main>
</el-container>
</el-container>
</template>
<script lang="ts">
// 组件
import LayoutHeader from "./components/Header.vue";
import LayoutAside from "./components/Aside.vue";
import LayoutMain from "./components/Main.vue";
export default {
name: "MainFrame",
components: {
LayoutHeader,
LayoutAside,
LayoutMain,
},
setup()
{
return {};
},
};
</script>
<style lang="scss" scoped>
@media screen {
.layout-container {
height: 100vh;
width: 100vw;
max-height: 100vh;
max-width: 100vw;
.layout-header {
height: 50px;
width: 100vw;
max-height: 50px;
max-width: 100vw;
padding: 0px;
}
.layout-container-down {
height: calc(100vh - 50px);
max-height: calc(100vh - 50px);
width: 100vw;
max-width: 100vw;
.layout-aside {
height: calc(100vh - 50px);
max-height: calc(100vh - 50px);
min-height: calc(100vh - 50px);
width: 200px;
overflow-x: hidden;
background-color: #2f4156;
}
.layout-main {
padding: 0px;
height: calc(100vh - 50px);
width: calc(100vw - 200px);
}
}
}
}
</style>

View File

@@ -0,0 +1,146 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-23 15:32:30
component: Aside
Copyright © CPIC All rights reserved
-->
<template>
<el-scrollbar class="sidebar-wrapper">
<el-menu
class="side-bar"
router
:default-active="currentPath"
background-color="#2f4156"
text-color="#fff"
active-text-color="#ffd04b"
>
<template v-for="route in routes">
<template v-if="!route.hidden">
<template v-if="hasOnlyChild(route.children)">
<!-- 当只有一个子路由时将这个子路由作为顶级菜单项 -->
<el-menu-item
:key="route.children[0].path"
:index="route.children[0].path"
class="sidebar-submenu"
>
<component
:is="route.children[0] && route.children[0].meta.icon"
class="icons"
/>
<template #title>
{{ route.children[0].meta && route.children[0].meta.title }}
</template>
</el-menu-item>
</template>
<template v-else>
<!-- 不止一个子路由可能是咩有子s路由或者有多个子路由 -->
<!-- 如果没有子路由就不渲染 -->
<el-sub-menu
v-if="route.children && route.children.length"
:key="route.path"
:index="route.path"
class="sidebar-submenu"
>
<template #title>
<component
:is="route.meta && route.meta.icon"
class="icons"
/>
<span>{{ route.meta && route.meta.title }}</span>
</template>
<template v-for="child in route.children">
<el-menu-item
v-if="!child.hidden"
:key="child.path"
:index="child.path"
class="sidebar-item"
>
<component
:is="child.meta && child.meta.icon"
class="icons"
/>
<template #title>
{{ child.meta && child.meta.title }}
</template>
</el-menu-item>
</template>
</el-sub-menu>
</template>
</template>
</template>
</el-menu>
</el-scrollbar>
</template>
<script lang="js">
import { hasOnlyChild } from "@/router/index.ts";
import { useRoute, useRouter } from "vue-router";
import { computed } from "vue";
export default {
name: "LayoutAside",
setup()
{
const userRout = useRoute();
const router = useRouter();
const routes = router.getRoutes();// as SideBarRouteRecordNormalized[];
const currentPath = computed(() =>
{
return userRout.path;
});
return { userRout, routes, currentPath, hasOnlyChild, };
},
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/public/variables.scss";
@import "@/assets/css/public/mixin.scss";
.sidebar-wrapper {
@include no-select;
height: 100%;
width: 100%;
}
:deep(.el-menu) {
border-right: none;
/* border-left: 5px solid #1d74b2; */
overflow: auto;
.el-menu-item {
font-weight: normal;
}
.el-sub-menu {
font-weight: normal;
}
.el-menu-item.is-active {
// background-color: #ffffff1f !important;
font-weight: 1000;
font-size: 15px;
color: #ffd04b;
}
}
.sidebar-submenu {
background-color: #2f4156 !important;
}
.sidebar-item {
background-color: #223142 !important;
}
/* .is-opened {
border-left: 5px solid #1d74b2;
} */
.icons {
width: 1em;
height: 1em;
margin-right: 8px;
}
</style>

View File

@@ -0,0 +1,118 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-23 15:32:30
component: Header
Copyright © CPIC All rights reserved
-->
<template>
<div class="header-wrapper">
<span class="company-name">CPIC</span>
<div class="version-wrapper">
<span>制度库后台管理</span>
<span>Build-20251021</span>
</div>
<div class="buttons-wrapper">
<component
:is="'SwitchButton'"
class="icons"
@click="Logout"
/>
</div>
</div>
</template>
<script lang="ts">
import { ElMessageBox } from "element-plus";
// import { logout } from "@/utils/account.js";
export default {
name: "LayoutHeader",
setup()
{
/**
* 退出登录
*/
const Logout = (): void =>
{
ElMessageBox.confirm(
"是否要退出系统?",
"",
{
confirmButtonText: "是",
cancelButtonText: "否",
type: "warning",
}
)
.then((): void =>
{
// debugger;
console.log( "退出" );
// logout();
})
.catch((): void => {});
};
return { Logout, };
},
};
</script>
<style lang="scss" scoped>
.header-wrapper {
// @include no-select;
height: 50px;
max-height: 50px;
padding: 0px 15px;
// position: relative;
display: flex;
justify-content: start;
align-items: center;
background-color: #1d74b2;
color: #fff;
// background-color: $banner-background-color;
span {
text-align: left;
}
>*+* {
margin-left: 10px;
}
.version-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: start;
font: {
size: 0.75rem;
}
>*+* {
margin-top: 1px;
}
}
.company-name {
font-size: 2rem;
}
.buttons-wrapper {
margin-left: auto;
padding-top: 5px;
// border: 1px solid salmon;
}
.icons {
width: 25px;
height: 25px;
// margin-right: 8px;
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,29 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-23 17:52:01
component: Main
Copyright © CPIC All rights reserved
-->
<template>
<el-scrollbar>
<router-view />
</el-scrollbar>
</template>
<script lang="ts">
export default {
name: "LayoutMain",
setup()
{
return {};
},
};
</script>
<style scoped>
.el-scrollbar {
height: 100%;
width: 100%;
/* background-color: #ecf2f9; */
}
</style>

View File

@@ -1,16 +1,32 @@
// eslint-disable-next-line // eslint-disable-next-line
import { createApp, VueElement } from "vue"; import { createApp, VueElement } from "vue";
import "./style.css"; import "./assets/css/index.scss";
import "./style.scss";
// 路由
// import { router, hasOnlyChild } from "./router/RouteIndex";
import { router } from "./router/index.ts";
// import App from "./App.vue"; // import App from "./App.vue";
import AppMain from "./AppMain.vue"; import AppMain from "./AppMain.vue";
import ElementPlus from "element-plus"; import ElementPlus from "element-plus";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import "element-plus/dist/index.css"; import "element-plus/dist/index.css";
// eslint-disable-next-line // eslint-disable-next-line
const app = createApp( AppMain ); const app = createApp( AppMain );
app.use( ElementPlus ); app.use( ElementPlus );
app.use( router );
// 引入element-icon
for ( const [key, component,] of Object.entries( ElementPlusIconsVue ))
{
app.component( key, component );
}
app.mount( "#app" ); app.mount( "#app" );
// eslint-disable-next-line // eslint-disable-next-line

View File

@@ -2,17 +2,124 @@
* @Author: Kane Wang <wangkane@qq.com> * @Author: Kane Wang <wangkane@qq.com>
* @Date: 2025-10-13 15:31:41 * @Date: 2025-10-13 15:31:41
* @LastEditors: Kane Wang * @LastEditors: Kane Wang
* @LastModified: 2025-10-13 15:37:20 * @LastModified: 2025-10-31 15:10:46
* @FilePath: src/router/index.ts * @FilePath: src/router/index.ts
* @Description: * @Description:
* *
* Copyright (c) 2025 by Kane All rights reserved * Copyright (c) 2025 by Kane All rights reserved
*/ */
import { createRouter, createWebHashHistory } from "vue-router"; import { createRouter, createWebHashHistory } from "vue-router";
import { type RouteRecordNormalized } from "vue-router";
// import index from "../layout/console/index.vue";
export declare interface SideBarRouteRecordNormalized extends RouteRecordNormalized
{
hidden?: boolean;
}
const routes = [
{
path: "/",
name: "root",
redirect: "Overview",
hidden: true,
},
{
path: "/desktop",
name: "Desktop",
meta: {
title: "工作台",
icon: "house",
},
component: () => import( "../layout/console/Index.vue" ),
children:[
{
path: "/overview",
name: "Overview",
meta: {
title: "总览",
icon: "house",
},
component: () => import( "@/views/console/desktop/Overview.vue" ),
},
],
},
{
path: "/data",
name: "Data",
meta: {
title: "制度库管理",
icon:"Collection",
},
component: () => import( "../layout/console/Index.vue" ),
children:[
{
path: "/regulatory-management",
name:"RegulatoryManagement",
meta: {
title: "制度文件管理",
icon:"document",
},
component: ()=> import( "@/views/console/data/RegulatoryManagement.vue" ),
},
{
path: "/department-management",
name: "DepartmentManagement",
meta:{
title: "组织机构管理",
icon: "OfficeBuilding",
},
component: ()=> import( "@/views/console/data/RegulatoryManagement.vue" ),
},
{
path: "/new-regulatory",
name: "NewRegulatory",
meta: {
title: "测试用 - 新建",
icon: "OfficeBuilding",
},
hidden: false,
component: () => import( "@/views/console/data/NewRegulatory.vue" ),
},
{
path: "/upload-regulatory",
name: "UploadRegulatory",
meta: {
title: "测试用 - 上传制度",
icon: "OfficeBuilding",
},
hidden: false,
component: () => import( "@/views/console/data/UploadRegulatory.vue" ),
},
],
},
];
const router = createRouter({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),
routes:[], routes: routes,
}); });
export default router; // 工具函数
/* eslint-disable */
function hasOnlyChild( children: any ): boolean
{
if ( !children )
{
return false;
}
const routes = children.filter(( item: any )=>
{
return !item.hidden;
});
if ( routes.length === 1 )
{
return true;
}
return false;
}
export { router, hasOnlyChild };

View File

@@ -0,0 +1,21 @@
body
{
width: 100vw;
height: 100vh;
padding: 0px;
margin: 0px;
overflow: hidden;
// @include no-select
-webkit-touch-callout: none;
-moz-user-select: none;
/*火狐*/
-webkit-user-select: none;
/*webkit浏览器*/
-ms-user-select: none;
/*IE10*/
-khtml-user-select: none;
/*早期浏览器*/
user-select: none;
}

View File

@@ -0,0 +1,26 @@
/**
* @Author: Kane Wang <wangkane@qq.com>
* @Date: 2025-10-28 10:13:04
* @LastEditors: Kane Wang
* @LastModified: 2025-10-28 10:13:04
* @FilePath: src/types/regulatory.ts
* @Description: 和制度相关的类型定义
*
* Copyright (c) 2025 by Kane All rights reserved
*/
interface RegulatoryData {
department_name: string;
release_year: string;
regulatory_name: string;
comment: string;
regulatory_files: null | RegulatoryFile[]
}
interface RegulatoryFile {
regulatory_file_name: string;
file_url: string;
file_type: string
}
export { type RegulatoryData, type RegulatoryFile };

View File

@@ -0,0 +1,10 @@
/**
* @Author: Kane Wang <wangkane@qq.com>
* @Date: 2025-10-23 16:52:10
* @LastEditors: Kane Wang
* @LastModified: 2025-10-23 17:04:54
* @FilePath: src/utils/utils.ts
* @Description:
*
* Copyright (c) 2025 by Kane All rights reserved
*/

View File

@@ -0,0 +1,173 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-30 15:06:18
component: NewRegulatory
Copyright © CPIC All rights reserved
-->
<template>
<div class="wrapper">
<div class="query-box-wrapper">
<el-row :gutter="10">
<el-col :span="1">
<span>名称</span>
</el-col>
<el-col :span="10">
<el-input style="text-align:center;" />
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="1">
<span>部门</span>
</el-col>
<el-col :span="4">
<el-input />
</el-col>
<el-col :span="2">
<span>发布修订年份</span>
</el-col>
<el-col :span="4">
<el-input />
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="1">
<span>备注</span>
</el-col>
<el-col :span="10">
<el-input type="textarea" :rows="3" />
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="3">
<div class="button-wrapper-left">
<el-button type="primary" icon="document" @click="showUploadFileDialog">
新增文档
</el-button>
<el-button type="primary" icon="document">
新增文档
</el-button>
</div>
</el-col>
<el-col :span="5" />
<el-col :span="3">
<div class="button-wrapper-right">
<el-button type="primary" icon="document">
提交
</el-button>
</div>
</el-col>
</el-row>
</div>
<el-table
width="100%" stripe
border
:head-cell-style="headerCellStyle"
>
<el-table-column label="文件名" align="center" width="200px">
<template #default="file">
<span>{{ file.row.filename }}</span>
</template>
</el-table-column>
<el-table-column label="文件类型" align="center">
<template #default="file">
<span>{{ file.row.filename }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="200px">
<el-button type="primary" icon="search">
查看
</el-button>
</el-table-column>
</el-table>
<div class="upload-dialog-wrapper">
<el-dialog
v-model="ui.showUploadDialog" title="上传文件"
width="600px"
:close-on-click-model="false" :close-on-press-escape="false"
:show-close="true"
>
<el-upload
drag
:action="ui.urlFileUpload"
name="files"
:show-file-list="false"
:data="ui.uploadParameters"
:on-success="onUploadSuccess"
>
<el-icon class="el-icon--upload">
<upload-filled />
</el-icon>
<div class="el-upload__text">
将文件拖到此处<em>点击上传</em>
</div>
</el-upload>
</el-dialog>
</div>
</div>
</template>
<script lang="ts">
import {reactive, ref} from "vue";
export default {
name: "NewRegulatory",
components: {},
setup()
{
const ui = reactive({
showUI: true,
showUploadDialog: false,
urlFileUpload: "",
uploadParameters: {
"file-name": "1234",
},
showFileList: false,
});
const headerCellStyle = reactive(
{
textAlign: "center",
}
);
const cellStyle = reactive({
textAlign: "center",
});
const onUploadSuccess = ()=> {};
const showUploadFileDialog = (): void =>
{
ui.showUploadDialog = true;
};
return {
ui,
headerCellStyle,
cellStyle,
onUploadSuccess,
showUploadFileDialog,
};
},
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/public/_public.scss";
.wrapper {
// max-width: 800px;
min-width: 1024px;
margin: 10px 10px 10px 10px;
>*+* {
margin-top: 10px;
}
}
.query-box-wrapper
{
@include query-box-wrap;
}
:deep(.el-input) .el-input__inner {
text-align: center;
}
</style>

View File

@@ -0,0 +1,127 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-23 21:40:24
component: RegulatoryManagement
Copyright © CPIC All rights reserved
-->
<template>
<div class="wrapper">
<el-row :gutter="10">
<el-col span="24">
<el-button
type="warning"
icon="upload"
>
上传
</el-button>
<el-button
type="primary"
icon="refresh"
>
刷新
</el-button>
</el-col>
</el-row>
<el-table
width="100%" stripe
:header-cell-style="headerCellStyle"
border
:data="ui.regulatoryData"
>
<el-table-column label="部门" align="center" width="200px">
<template #default="regulatory">
<span>{{ regulatory.row.department_name }}</span>
</template>
</el-table-column>
<el-table-column width="150px" label="发布、修订年份" align="center">
<template #default="regulatory">
<span>{{ regulatory.row.release_year }}</span>
</template>
</el-table-column>
<el-table-column label="制度名称" align="center" :cell-style="cellStyle">
<template #default="regulatory">
<span>{{ regulatory.row.regulatory_name }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="200px">
<el-button
type="primary"
icon="search"
>
查看
</el-button>
<el-button type="warning" icon="document">
编辑
</el-button>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts">
import { reactive } from "vue";
import { type RegulatoryData } from "@/types/regulatory/regulatory.ts";
interface UI
{
showUI: boolean,
showUploadDialog: boolean,
tablePageSize: number,
tableCurrentPageIndex: number,
regulatoryData: RegulatoryData[],
}
export default {
name: "RegulatoryManagement",
setup()
{
const headerCellStyle = reactive(
{
textAlign: "center",
}
);
const cellStyle = reactive({
textAlign: "center",
});
const ui:UI = reactive({
showUI: true,
showUploadDialog: false,
tablePageSize: 10,
tableCurrentPageIndex: 1,
regulatoryData: [
{
department_name: "信息技术部",
release_year: "2019",
regulatory_name: "关于印发修订后的《太平洋产险厦门分公司信息系统账号权限管理实施细则》的通知",
comment:"",
regulatory_files: [],
},
{
department_name: "信息技术部",
release_year: "2019",
regulatory_name: "关于印发修订后的《太平洋产险厦门分公司个人信息保护管理实施细则》的通知",
comment:"",
regulatory_files: [],
},
],
});
return { ui, headerCellStyle, cellStyle, };
},
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/public/mixin.scss";
.wrapper {
margin: 10px 10px 10px 10px;
>*+* {
margin-top: 10px;
}
}
.pagination_wrapper {
display: flex;
justify-content: flex-end;
}
</style>

View File

@@ -0,0 +1,78 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-28 11:18:51
component: UploadRegulatory
Copyright © CPIC All rights reserved
-->
<template>
<div class="wrapper">
<!-- <VuePdfEmbed v-if="ui.isPDF" :source="ui.fileURL" text-layer annotation-layer /> -->
<!-- <VueOfficePdf v-if="ui.isPDF" :src="ui.fileURL" @error="errorHandle" /> -->
<VueOfficeDocx v-if="ui.isXlsx" :src="ui.fileURL" @error="errorHandle" />
<VueOfficeExcel
v-if="ui.isXlsx"
:src="ui.fileURL"
@error="errorHandle"
/>
</div>
</template>
<script lang="ts">
import {reactive, ref } from "vue";
import { ElMessage } from "element-plus";
// import VuePdfEmbed, { useVuePdfEmbed } from "vue-pdf-embed";
import VueOfficePdf from "@vue-office/pdf";
import VueOfficeDocx from "@vue-office/docx";
import VueOfficeExcel from "@vue-office/excel";
import "vue-pdf-embed/dist/styles/annotationLayer.css";
import "vue-pdf-embed/dist/styles/textLayer.css";
import "@vue-office/excel/lib/index.css";
export default {
name:"UploadRegulatory",
components: {
// VueOfficePdf,
VueOfficeDocx,
VueOfficeExcel,
},
setup()
{
const ui = reactive({
showUI: true,
isPDF: false,
isDocx: false,
isXlsx: true,
// fileURL: "http://10.39.0.1:8080/regulatory/%E4%BF%A1%E6%81%AF%E6%8A%80%E6%9C%AF%E9%83%A8/%E5%85%B3%E4%BA%8E%E5%8D%B0%E5%8F%91%E3%80%8A%E5%A4%AA%E5%B9%B3%E6%B4%8B%E4%BA%A7%E9%99%A9%E5%8E%A6%E9%97%A8%E5%88%86%E5%85%AC%E5%8F%B8IT%E8%B5%84%E4%BA%A7%E7%AE%A1%E7%90%86%E5%8A%9E%E6%B3%95%E3%80%8B%EF%BC%882019%E5%B9%B4%E4%BF%AE%E8%AE%A2%EF%BC%89%E7%9A%84%E9%80%9A%E7%9F%A5/%E5%8E%A6%E5%A4%AA%E4%BF%9D%E4%BA%A7%E5%8F%91%E3%80%902019%E3%80%9146%E5%8F%B7%E5%85%B3%E4%BA%8E%E5%8D%B0%E5%8F%91%E3%80%8A%E5%A4%AA%E5%B9%B3%E6%B4%8B%E4%BA%A7%E9%99%A9%E5%8E%A6%E9%97%A8%E5%88%86%E5%85%AC%E5%8F%B8IT%E8%B5%84%E4%BA%A7%E7%AE%A1%E7%90%86%E5%8A%9E%E6%B3%95%E3%80%8B%EF%BC%882019%E5%B9%B4%E4%BF%AE%E8%AE%A2%EF%BC%89%E7%9A%84%E9%80%9A%E7%9F%A5.pdf",
// fileURL: "http://10.39.0.1:8080/regulatory/%E4%BF%A1%E6%81%AF%E6%8A%80%E6%9C%AF%E9%83%A8/%E5%85%B3%E4%BA%8E%E5%8D%B0%E5%8F%91%E3%80%8A%E5%A4%AA%E5%B9%B3%E6%B4%8B%E4%BA%A7%E9%99%A9%E5%8E%A6%E9%97%A8%E5%88%86%E5%85%AC%E5%8F%B8%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E9%9C%80%E6%B1%82%E7%AE%A1%E7%90%86%E5%8A%9E%E6%B3%95%EF%BC%882020%E5%B9%B4%E4%BF%AE%E8%AE%A2%EF%BC%89%E3%80%8B%E7%9A%84%E9%80%9A%E7%9F%A5/%E9%99%84%E4%BB%B62%EF%BC%9A%E4%B8%9A%E5%8A%A1%E9%9C%80%E6%B1%82%E8%AF%B4%E6%98%8E%E4%B9%A6.docx",
fileURL: "http://10.39.0.1:8080/regulatory/%E4%BF%A1%E6%81%AF%E6%8A%80%E6%9C%AF%E9%83%A8/%E5%85%B3%E4%BA%8E%E5%8D%B0%E5%8F%91%E3%80%8A%E5%A4%AA%E5%B9%B3%E6%B4%8B%E4%BA%A7%E9%99%A9%E5%8E%A6%E9%97%A8%E5%88%86%E5%85%AC%E5%8F%B8%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E9%9C%80%E6%B1%82%E7%AE%A1%E7%90%86%E5%8A%9E%E6%B3%95%EF%BC%882020%E5%B9%B4%E4%BF%AE%E8%AE%A2%EF%BC%89%E3%80%8B%E7%9A%84%E9%80%9A%E7%9F%A5/%E9%99%84%E4%BB%B64%EF%BC%9A%E5%88%86%E5%85%AC%E5%8F%B8%E8%87%AA%E5%BB%BA%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2%E6%83%85%E5%86%B5%E7%99%BB%E8%AE%B0%E8%A1%A8.xlsx",
});
const errorHandle = ()=>
{
ElMessage.error( "渲染文档出错!" );
};
return {
ui,
errorHandle, };
},
};
</script>
<style lang="scss">
.wrapper {
margin: 10px 10px 10px 10px;
width: calc(100% - 20px);
height: calc( 100vh - 70px);
// .VueOfficeExcel {
// height: calc( 100vh - 70px);
// }
>*+* {
margin-top: 10px;
}
}
</style>

View File

@@ -0,0 +1,32 @@
<!--
author: Kane Wang <wangkane@qq.com>
date: 2025-10-23 21:40:24
component: RegulatoryManagement
Copyright © CPIC All rights reserved
-->
<template>
<div class="wrapper">
总览
</div>
</template>
<script lang="ts">
export default {
name: "OverViews",
setup()
{
const ui = {};
return { ui, };
},
};
</script>
<style lang="scss" scoped>
@import "@/assets/css/public/mixin.scss";
.wrapper {
@include no-select;
margin: 5px;
border: 1px solid red;
}
</style>

View File

@@ -1 +1,8 @@
/// <reference types="vite/client" /> // / <reference types="vite/client" />
declare module "*.vue"
{
import type { DefineComponent } from "vue";
const vueComponent: DefineComponent<unknown, unknown, any>;
export default vueComponent;
}

View File

@@ -1,16 +1,9 @@
// {
// "files": [],
// "references": [
// {
// "path": "./tsconfig.node.json"
// },
// {
// "path": "./tsconfig.app.json"
// }
// ],
// }
{ {
"compilerOptions": { "compilerOptions": {
// "allowJs": true,
// "declaration": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"useDefineForClassFields": true, "useDefineForClassFields": true,
@@ -45,7 +38,7 @@
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.vue", "src/**/*.vue",
"*.d.ts", "*.d.ts",
"src/router/index.d.ts", ".vscode/bak/RouteIndex.d.ts",
"vite.config.*", "vite.config.*",
"vitest.config.*", "vitest.config.*",
"cypress.config.*", "cypress.config.*",

View File

@@ -19,7 +19,8 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"erasableSyntaxOnly": true, "erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true "noUncheckedSideEffectImports": true,
"declaration":true,
}, },
"include": ["vite.config.ts"] "include": ["vite.config.ts"]
} }

View File

@@ -1,7 +1,30 @@
import { defineConfig } from 'vite' import { defineConfig } from "vite";
import vue from '@vitejs/plugin-vue' import vue from "@vitejs/plugin-vue";
import path from "path";
/* eslint-disable */
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue(),],
}) resolve: {
//配置别名
alias: [
{
find: /^~/,
replacement: "",
},
{
find: "@",
replacement: path.resolve( __dirname, "src" ),
},
],
},
css: {
preprocessorOptions: {
scss: {
// additionalData: '@import "./src/assets/css/public/variables.scss";@import "./src/assets/css/public/mixin.scss";',
// additionalData: '@import "@/assets/css/public/variables.scss";',
},
},
},
});

68
开发日志.md Normal file
View File

@@ -0,0 +1,68 @@
# 前端
## 问题
### vue3 引入@路径
#### 引入path模块问题
node.js 自带的path模块是JavaScript代码要引入ts文件需要安装@type/node模块
```shell
npm install @types/node --save-dev
```
之后就可以加载path。在 vite.config.ts 中加上
```typescript
import path from "path";
resolve: {
//配置别名
alias: [
{
find: /^~/,
replacement: "",
},
{
find: "@",
replacement: path.resolve( __dirname, "src" ),
},
],
},
```
### tomcat 跨域下载文件
tomcat 默认是不支持跨域的不做配置使用vue下载文件会有Access-Control-Allow-Origin问题。
解决方法: 编辑 web.xml 文件,找到
```xml
<!-- The mapping for the HTTP header security Filter -->
```
在下面添加
```xml
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```
重启 tomcat 解决。
## 组件
### pdf预览组件
使用