ssts-hospital-web-master项目实战记录十五:项目迁移-基础模块实现(file-system-object)

记录时间:2024-02-25

一、准备工作

【使用“文心一言”搜索使用ts实现类模块】

在 TypeScript 中,类可以作为模块的一部分被导出,这样其他模块就可以导入并使用这些类。以下是如何使用 TypeScript 实现类模块的基本步骤:

步骤 1:定义类模块

首先,在一个 TypeScript 文件中定义一个或多个类,并使用 export 关键字导出它们。这个文件就是你的类模块。

例如,创建一个名为 user.ts 的文件,其中包含一个 User 类:

typescript复制代码
  // user.ts
  export class User {
  private name: string;
  private age: number;
   
  constructor(name: string, age: number) {
  this.name = name;
  this.age = age;
  }
   
  greet(): void {
  console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
  }
  }

步骤 2:导入类模块

在另一个 TypeScript 文件中,使用 import 关键字导入你定义的类。

例如,在 main.ts 文件中导入 User 类:

typescript复制代码
  // main.ts
  import { User } from './user'; // 假设 user.ts 在同一目录下
   
  // 创建一个 User 实例
  const user = new User('Alice', 30);
   
  // 调用 greet 方法
  user.greet(); // 输出:Hello, my name is Alice and I'm 30 years old.

步骤 3:编译 TypeScript 文件

使用 TypeScript 编译器(tsc)编译你的 TypeScript 文件。如果你已经全局安装了 TypeScript,可以在命令行中运行以下命令来编译 main.ts 文件:

bash复制代码
  tsc main.ts

这将生成一个名为 main.js 的 JavaScript 文件。

步骤 4:运行 JavaScript 文件

如果你使用 Node.js 环境,可以直接运行生成的 main.js 文件:

bash复制代码
  node main.js

如果你在浏览器中运行代码,可以将 main.js 文件包含在一个 HTML 文件中,并使用 <script> 标签引用它。

注意事项

  • 确保在导入类时,路径是正确的。如果 user.ts 和 main.ts 不在同一目录下,你需要提供正确的相对路径或绝对路径。
  • 如果你在类模块中使用了 ES6 模块语法(即使用 export 和 import),确保你的 TypeScript 配置文件(tsconfig.json)中的 module 选项设置为 "es6" 或 "es2015"(或其他符合 ES6 模块语法的选项)。
  • TypeScript 编译器会自动处理模块之间的依赖关系,并在编译时生成相应的代码。你不需要手动管理这些依赖关系。

 

【使用“文心一言”搜索使用ts模拟实现ActiveXObject("Scripting.FileSystemObject"),使用原函数定义,内部调用http接口实现逻辑】

由于ActiveXObject("Scripting.FileSystemObject")是特定于Windows Script Host (WSH) 的对象,它提供了对文件系统的直接访问,这在浏览器中是不可能直接实现的,因为出于安全考虑,浏览器限制了访问本地文件系统的能力。但是,我们可以在Node.js环境中使用TypeScript来模拟这个对象,并通过HTTP接口来执行实际的文件操作。

在Node.js中,我们可以使用fs模块来访问文件系统,并通过axiosnode-fetch等库来发送HTTP请求。以下是一个使用TypeScript模拟Scripting.FileSystemObject的示例,内部通过HTTP接口实现文件操作逻辑:

首先,安装必要的依赖:

bash复制代码
  npm install axios

然后,我们可以创建一个TypeScript文件来模拟Scripting.FileSystemObject

typescript复制代码
  // fileSystemObject.ts
   
  import axios, { AxiosResponse } from 'axios';
   
  interface FileSystemObject {
  CreateTextFile(filename: string, overwrite?: boolean): TextStream;
  // 其他Scripting.FileSystemObject的方法...
  }
   
  interface TextStream {
  WriteLine(text: string): void;
  Close(): void;
  // 其他TextStream的方法...
  }
   
  class MockFileSystemObject implements FileSystemObject {
  private baseUrl: string;
   
  constructor(baseUrl: string) {
  this.baseUrl = baseUrl;
  }
   
  CreateTextFile(filename: string, overwrite = false): TextStream {
  const url = `${this.baseUrl}/files/${filename}`;
  const params = overwrite ? { method: 'POST' } : { method: 'PUT' };
   
  return {
  WriteLine: async (text: string) => {
  await axios.post(url, text, {
  headers: {
  'Content-Type': 'text/plain',
  },
  });
  },
  Close: async () => {
  // 在这里可以发送一个请求来标记文件写入完成
  // 但如果WriteFileLine是逐个调用的,那么这一步可能不是必要的
  },
  };
  }
   
  // 实现其他Scripting.FileSystemObject的方法...
  }
   
  export default MockFileSystemObject;

在上面的代码中,我们创建了一个MockFileSystemObject类,它实现了FileSystemObject接口。CreateTextFile方法接收一个文件名和一个可选的overwrite参数,并返回一个模拟的TextStream对象。TextStream对象有一个WriteLine方法,它发送一个HTTP POST请求到服务器来写入文本内容。

请注意,这个模拟实现假定服务器已经实现了处理文件上传和创建的逻辑。你需要根据你的后端API来调整URL和请求方法。

要使用这个模拟的FileSystemObject,你可以这样做:

typescript复制代码
  import MockFileSystemObject from './fileSystemObject';
   
  const fso = new MockFileSystemObject('http://localhost:3000');
   
  const textStream = fso.CreateTextFile('example.txt', true);
  textStream.WriteLine('Hello, world!');
  textStream.Close();

在这个例子中,我们创建了一个MockFileSystemObject实例,并通过它创建了一个TextStream来写入一个文件。WriteLine方法会发送一个HTTP POST请求到http://localhost:3000/files/example.txt,假设你的服务器在这个地址上接收文件内容。

请确保你的服务器能够处理这些请求,并根据需要更新URL和其他参数。

 

【关于模拟实现ActiveXObject("Scripting.FileSystemObject")相关说明】

调用示例:

var fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso.FolderExists(folder)) {//存在文件夹
if (fso.FileExists(filename)) {//存在文件
var openFile = fso.OpenTextFile(filename, 8, false);
openFile.WriteLine(log);
openFile.Close();
}
else {//不存在文件
var newFileObject = fso.CreateTextFile(filename, true);
newFileObject.WriteLine(log);
newFileObject.Close();
}
}
else {//不存在文件夹
CreateFolder(fso, folder);
//var newFolderName = fso.CreateFolder(folder);
var newFileObject = fso.CreateTextFile(filename, true);
newFileObject.WriteLine(log);
newFileObject.Close();
}

//=========================================
//FileSystemObject说明
//=========================================
CreateTextFile方法
语法:object.CreateTextFile (filename, [ overwrite, [ unicode ]])
作用:创建指定的文件名, 并返回一个TextStream对象, 该对象可用于对文件进行读取或写入。
说明:
object 必需,是FileSystemObject或Folder对象的名称。
filename 必需,指示要创建的文件的字符串表达式。
overwrite 可选,指示是否可重写现有文件的“Boolean”值。如果可重写文件,则该值为“True”;如果不可重写则为“False”。如果省略, 则可以覆盖现有文件。
unicode 可选,指示文件是否创建为 Unicode 或 ASCII 文件的“Boolean”值。如果文件创建为 Unicode 文件;该值为“True”;如果文件创建为 ASCII 文件,该值为“False”。如果忽略,则假设为 ASCII 文件。

OpenTextFile方法  
语法:object.OpenTextFile(filename[, iomode[, create[, format]]])  
作用:打开一个指定的文件并返回一个 TextStream 对象,该对象可用于对文件进行读、写、追加操作。  
说明:  
·iomode 参数可为下面设置值中的任何值:  
ForReading 1 打开一个只读文件,不能对此文件进行写操作。  
ForWriting 2 打开一个用于写操作的文件。如果和此文件同名的文件已存在,则覆盖以前内容。  
ForAppending 8 打开一个文件并写到文件的尾部。  
注意:在VBA帮助里是没有ForWriting的,其实是有的,VBA帮助也是有错误的。另外,这些常数在使用前要先声明,或者直接用数值。  
·create 可选的,它表示如果指定的 filename 不存在是否可以创建一个新文件。如果创建新文件,其值为 True。若不创建文件其值为 False。缺省值为 False。  
·Format 参数可为下面设置值中的任何值:  
TristateUseDefault –2 使用系统缺省打开文件。  
TristateTrue –1 以 Unicode 格式打开文件。  
TristateFalse 0 以 ASCII 格式打开文件。

示例:  
Dim f  
Set f = fso.OpenTextFile("c:\testfile.txt", 2, True)  
或者:  
Const ForWriting = 2  
Set f = fso.OpenTextFile("c:\testfile.txt", ForWriting, True)  
这两者功能是一样的,一个声明了常量,一个直接用数值。都是在C盘创建文件testfile.txt(如不存在),或以写的方式打开(如存在)。
 

二、file-system-object模块实现

framework/file-system-object/index.ts

import { clientWebApi } from '@/common'

// 定义 FileSystemObject 接口,代表文件系统操作的对象
interface FileSystemObject {
  // 判断指定文件夹路径是否存在
  FolderExists(folderPath: string): Promise<string>
  // 创建指定路径的文件夹
  CreateFolder(folderPath: string): Promise<boolean>
  // 判断指定文件路径是否存在
  FileExists(filePath: string): Promise<boolean>
  // 创建或覆盖一个文本文件,并返回一个 TextStream 对象来操作这个文件
  CreateTextFile(
    filename: string,
    create?: boolean,
    overwrite?: boolean,
    encoding?: string
  ): TextStream
  // 打开一个文本文件,返回一个 TextStream 对象来操作这个文件
  OpenTextFile(
    filename: string,
    iomode?: number | string,
    create?: boolean,
    format?: number | string
  ): TextStream
}

// 定义 TextStream 接口,代表文本流对象,用于文件读写操作
interface TextStream {
  // 向文本流中写入一行文本
  WriteLine(text: string): void
  // 从文本流中读取一行文本
  ReadLine(filename: string): Promise<string | null>
  // 从文本流中读取所有行文本
  ReadAllLines(filename: string): Promise<string | null>
  // 关闭文本流
  Close(): void
}

// 实现 FileSystemObject 接口的FileSystemObjectImpl类
class FileSystemObjectImpl implements FileSystemObject {
  public async FolderExists(folderPath: string): Promise<string> {
    // console.log('FolderExists:', folderPath)
    const result = await clientWebApi('/api/FileSystem/FolderExists', {
      folderPath: folderPath
    })
    return result
  }

  public async CreateFolder(folderPath: string): Promise<boolean> {
    // console.log('CreateFolder:', folderPath)
    const result = await clientWebApi('/api/FileSystem/CreateFolder', {
      folderPath: folderPath
    })
    return result
  }

  public async FileExists(filePath: string): Promise<boolean> {
    //console.log('FileExists:', filePath)
    const result = await clientWebApi('/api/FileSystem/FileExists', {
      filePath: filePath
    })
    return result
  }

  public CreateTextFile(
    filename: string,
    create?: boolean,
    overwrite?: boolean,
    encoding?: string
  ): TextStreamImpl {
    // console.log('CreateTextFile:', filename, overwrite, encoding)

    //不做实现
    return new TextStreamImpl(filename, create, overwrite, encoding) // 返回相应模式的TextStreamImpl实例
  }

  public OpenTextFile(
    filename: string,
    iomode?: number | string,
    create?: boolean,
    format?: number | string
  ): TextStream {
    // console.log('CreateTextFile:', filename, iomode, create, format)

    // iomode:支持 1|'r'(读)、2|'w'(写)和 8|'a'(追加)模式
    // overwrite:支持 true|'true'(覆盖)和 false|'false'(不覆盖)模式
    let overwrite = false
    switch (iomode) {
      case 1:
      case 'r':
        // 读模式,不需要覆盖或指定unicode
        break
      case 2:
      case 'w':
        // 写模式,需要覆盖
        overwrite = true
        break
      case 8:
      case 'a':
        // 追加模式,不需要覆盖
        break
      default:
        throw new Error(`Unsupported mode: ${iomode}`)
    }

    // encoding 支持ascii(ASCII)|utf8(UTF-8)|unicode(Unicode)|gb2312(GB2312)模式
    let encoding = 'ascii'
    // format:支持 -2|'default'(默认)、-1|'unicode'(Unicode)、 0|'ascii'(ASCII)模式、 1|'utf8'(UTF-8)模式|'gb2312' (GB2312)模式
    //TristateUseDefault –2 使用系统缺省打开文件。
    //TristateTrue –1 以 Unicode 格式打开文件。
    //TristateFalse 0 以 ASCII 格式打开文件。
    switch (format) {
      case -2:
      case 'default':
      case 'ascii':
        encoding = 'ascii'
        break
      case -1:
      case 'unicode':
        encoding = 'unicode'
        break
      case 0:
      case 'utf8':
        encoding = 'utf8'
        break
      case 1:
      case 'gb2312':
        encoding = 'gb2312'
        break
      default:
    }

    // 创建并返回 TextStreamImpl 实例
    return new TextStreamImpl(filename, create, overwrite, encoding)
  }
}

// 实现 TextStream 接口的 TextStreamImpl 类
class TextStreamImpl implements TextStream {
  private filename: string
  private create: boolean
  private overwrite: boolean
  private encoding: string

  // 构造函数,接收文件路径和模式作为参数
  constructor(
    filename: string,
    create?: boolean,
    overwrite?: boolean,
    encoding?: string
  ) {
    this.filename = filename
    this.create = create ?? false // 使用空值合并运算符来设置默认值
    this.overwrite = overwrite ?? false // 使用空值合并运算符来设置默认值
    this.encoding = encoding ?? 'ascii'
    console.log(
      'TextStreamImpl:',
      this.filename,
      this.create,
      this.overwrite,
      this.encoding
    )
  }

  // 实现 WriteLine 方法,接收一个字符串参数,并将其输出到控制台
  public async WriteLine(text: string): Promise<void> {
    try {
      await clientWebApi('/api/FileSystem/WriteLine', {
        text,
        filename: this.filename,
        create: this.create,
        overwrite: this.overwrite,
        encoding: this.encoding
      })
    } catch (error) {
      // console.error('Error writing to text stream:', error)
    }
  }

  // 实现 ReadLine 方法,从文本流中读取一行文本
  public async ReadLine(filename: string): Promise<string | null> {
    try {
      const result = await clientWebApi('/api/FileSystem/ReadLine', {
        filename,
        encoding: this.encoding
      })
      return result
    } catch (error) {
      // console.error('Error reading line from file:', error)
      return null
    }
  }

  // 实现 ReadLine 方法,从文本流中读取所有行文本
  public async ReadAllLines(filename: string): Promise<string | null> {
    try {
      const result = await clientWebApi('/api/FileSystem/ReadAllLines', {
        filename,
        encoding: this.encoding
      })
      return result
    } catch (error) {
      // console.error('Error reading all lines from file:', error)
      return null
    }
  }

  // 实现 Close 方法,关闭文本流
  public Close(): void {
    // 不做实现
    // console.log('Text stream closed:', this.filename)
  }
}

export { FileSystemObjectImpl, TextStreamImpl }
 

三、调用示例

test-framework-fso.vue

<script setup lang="ts">
import { onMounted } from 'vue'
import { hydate } from '@/common'
import { FileSystemObjectImpl } from '@/framework/file-system-object'

const TestFileSystemObjectImpl = function () {
  console.log('TestFileSystemObjectImpl begin')

  const LogTestDir = 'D:\\LogInfo\\LogTest'
  console.log('LogTerminalInfoDir:', LogTestDir)

  const fso = new FileSystemObjectImpl()

  fso.FolderExists(LogTestDir).then((result) => {
    console.log('FolderExists:', result)
    if (!result) {
      fso.CreateFolder(LogTestDir)
    }
  })

  const filePath = `${LogTestDir}\\log.txt`
  console.log('filePath:', filePath)
  fso.FileExists(filePath).then((result) => {
    console.log('FileExists:', result)

    if (!result) {
      const textStream = fso.CreateTextFile(filePath, true)
      const line = hydate(new Date()).format('YYYY-MM-DD HH:mm:ss.SSS')
      textStream.WriteLine(line)
      textStream.Close()
    } else {
      const textStream = fso.OpenTextFile(filePath, 8, true)
      const line = hydate(new Date()).format('YYYY-MM-DD HH:mm:ss.SSS')
      textStream.WriteLine(line)
      textStream.Close()
    }
  })

  fso.FileExists(filePath).then((result) => {
    console.log('FileExists', result)
    if (result) {
      const textStream = fso.OpenTextFile(filePath, 8)
      textStream.ReadLine(filePath).then((result) => {
        console.log('ReadLine:', result)
      })
      textStream.ReadAllLines(filePath).then((result) => {
        console.log('ReadAllLines:', result)
      })
      textStream.Close()
    }
  })

  console.log('TestFileSystemObjectImpl end')
}

onMounted(() => {
  console.log('test-framework.vue', 'mounted')

  TestFileSystemObjectImpl()
})
</script>

<template>
  <div>
    <title>测试框架</title>
  </div>
</template>

<style scoped></style>

 

三、运行测试

1.文件夹《D:/LogInfo/LogTest》不存在

  

2.文件夹《D:/LogInfo/LogTest》已存在

 

 

 

posted @ 2024-02-25 17:18  lizhigang  阅读(2)  评论(0编辑  收藏  举报