# 前端

## 问题

### 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预览组件

使用

## 技术

### element-plus 文件上传

element-plus 文件上传组件的响应函数，作为:on-success属性值。要传递的参数作为:data属性值。

```typescript
import { type FileUploadResponse } from "@/utils/fileUpload.js";
import { type UploadProps, type UploadFile, type UploadFiles, ElMessage, ElMessageBox } from "element-plus";

const onUploadSuccess: UploadProps["onSuccess"] = ( response: FileUploadResponse, uploadFile: UploadFile, uploadFiles: UploadFiles ): void =>
        {
            //  先判断成功标志位
            if ( response.success )
            {
                // 成功，发出导入报表请求
                if ( response.fileList.length === 0 )
                {
                    // 上传文件路径有问题，提示一下
                    ElMessageBox.confirm(
                        "上传文件的保存路径有误，请联系开发人员。",
                        "上传文件错误",
                        {
                            confirmButtonText: "确定",
                            type: "warning",
                            center: true,
                        }
                    )
                        .then((): void => {})
                        .catch((): void => {});
                }

                const request: ImportBIReportRequest = {
                    filePath: response.fileList[0],
                    reportType: ui.selectedReportType,
                    firstRow: ui.firstRow,
                    sheetIndex: ui.sheetIndex,
                };

                console.log( "请求参数", request );

                // 发出请求
                importBIReport( request, importResponseHandler );
            }
            else
            {
                // 失败了，提示一下
                ElMessageBox.confirm(
                    response.message,
                    "上传文件错误",
                    {
                        confirmButtonText: "确定",
                        type: "warning",
                        center: true,
                    }
                )
                    .then((): void => {})
                    .catch((): void => {});
            }
        };
```

### typescript 的安全链式调用 和 强制链式调用

在链式调用时，在成员访问操作符前加上？，表示安全链式调用；加上！表示强制链式调用。

如果？前的属性存在，则正常调用，否则返回null。

```typescript
// 这里 Error对象定义的stack是可选参数，如果这样写的话编译器会提示
// 出错 TS2532: Object is possibly 'undefined'.
return new Error().stack.split('\n');

// 我们可以添加?操作符，当stack属性存在时，调用 stack.split。
// 若stack不存在，则返回空
return new Error().stack?.split('\n');

// 以上代码等同以下代码, 感谢 @dingyanhe 的监督
const err = new Error();
return err.stack && err.stack.split('\n');
```

强制链式调用表示！前的属性一定会存在。

```typescript
// 这里 Error对象定义的stack是可选参数，如果这样写的话编译器会提示
// 出错 TS2532: Object is possibly 'undefined'.
new Error().stack.split('\n');

// 我们确信这个字段100%出现，那么就可以添加！，强调这个字段一定存在
new Error().stack!.split('\n');
```

# mysql

my.cnf 文件

```
[client]
port = 3306
socket =/mysql/data/mysqltmp/mysqld.sock
default-character-set = utf8mb4

[mysql]
prompt = [\\u@\\h][\\d]>\\_

[mysqld]
# basic settings #
port = 3306 #服务器的端口号
#路径设置，必须和上文的一致
basedir = /mysql/mysql-9.5.0
datadir = /mysql/data/mysqldata_u01/mysqldb
socket = /mysql/data/mysqltmp/mysqld.sock
pid-file = /mysql/mysql-9.5.0/mysqld.pid
tmpdir = /mysql/data/mysqltmp
user = mysql
sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER"
autocommit = 1
character_set_server=utf8mb4
transaction_isolation = READ-COMMITTED
explicit_defaults_for_timestamp = 1
max_allowed_packet = 96M
slave_pending_jobs_size_max= 100M
event_scheduler = 1
lower_case_table_names = 1

# connection #
interactive_timeout = 1800
wait_timeout = 1800
lock_wait_timeout = 1800
skip_name_resolve = 1
max_connections = 1000
max_user_connections = 1000 
max_connect_errors = 10

# session memory setting #
read_buffer_size = 2M
read_rnd_buffer_size = 4M
sort_buffer_size = 4M
tmp_table_size = 8M
join_buffer_size = 8M

# log settings #
slow_query_log = 1
log-error =/mysqlslowlog/error.log
slow-query-log-file=/mysqlslowlog/slowquery.log
general_log_file = /mysqlslowlog/general.log
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_slow_slave_statements = 1
log_throttle_queries_not_using_indexes = 10
expire_logs_days = 5
long_query_time = 2
min_examined_row_limit = 100
binlog-rows-query-log-events = 1
log-bin-trust-function-creators = 1
log-slave-updates = 1

# innodb settings #
innodb_page_size = 16K
innodb_buffer_pool_size=20G
innodb_buffer_pool_instances = 16
innodb_buffer_pool_load_at_startup = 1
innodb_buffer_pool_dump_at_shutdown = 1
innodb_lru_scan_depth = 1024
innodb_lock_wait_timeout = 5
innodb_io_capacity = 2048
innodb_io_capacity_max = 4096
innodb_flush_method = O_DIRECT
innodb_file_format = Barracuda
innodb_file_format_max = Barracuda
innodb_undo_logs = 128
innodb_undo_tablespaces = 3
innodb_flush_neighbors = 1
innodb_log_file_size = 1G
innodb_log_files_in_group = 2
innodb_log_buffer_size = 2M
innodb_purge_threads = 4
innodb_large_prefix = 1
innodb_thread_concurrency = 16
innodb_print_all_deadlocks = 1
innodb_strict_mode = 1
innodb_sort_buffer_size = 4M
innodb_write_io_threads = 4             
innodb_read_io_threads = 4 
innodb_file_per_table = 1
innodb_stats_persistent_sample_pages = 64
innodb_autoinc_lock_mode = 2

# semi sync replication settings #
plugin_load = "validate_password.so;rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 3000
rpl_semi_sync_slave_enabled = 1

# password plugin #
#密码策略，密码16字节长，数字字母大小写和特殊字符，每种至少两个字符。
validate_password_policy=2
validate_password_length=16
validate_password_mixed_case_count=2
validate_password_number_count=2
validate_password_special_char_count=3

# 5.7 #
# new innodb setting #
loose_innodb_numa_interleave=1
innodb_buffer_pool_dump_pct = 40
innodb_page_cleaners = 4
innodb_undo_log_truncate = 1
innodb_max_undo_log_size = 2G
innodb_purge_rseg_truncate_frequency = 128
# new replication setting #
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 8
slave_preserve_commit_order=1
slave_transaction_retries=128
# other change setting #
binlog_gtid_simple_recovery=1
log_timestamps=system
show_compatibility_56=on

# patch #
symbolic_links=0
```

初始化

```
/mysql/mysql-9.5.0/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql --initialize --console
```

root密码 p)daqvACh5<s
