diff --git a/package-lock.json b/package-lock.json index 4581b3c..9aa607e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3687,18 +3687,18 @@ } }, "node_modules/vite": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.2.tgz", - "integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", - "tinyglobby": "^0.2.12" + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" diff --git a/server/Program.cs b/server/Program.cs index 0b3c10c..cde87b1 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -48,6 +48,12 @@ try ); }); } + builder.Services.AddCors(options => + { + options.AddPolicy("Users", policy => policy + .AllowAnyOrigin() + ); + }); // Add Swagger builder.Services.AddControllers(); diff --git a/server/src/Controllers.cs b/server/src/Controllers.cs index 968ab0a..9bdae91 100644 --- a/server/src/Controllers.cs +++ b/server/src/Controllers.cs @@ -180,8 +180,8 @@ public class JtagController : ControllerBase /// 设备地址 /// 设备端口 [HttpGet("GetDeviceIDCode")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] public async ValueTask GetDeviceIDCode(string address, int port) { var jtagCtrl = new JtagClient.Jtag(address, port); @@ -237,8 +237,9 @@ public class JtagController : ControllerBase /// 设备地址 /// 比特流文件 [HttpPost("UploadBitstream")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] public async ValueTask UploadBitstream(string address, IFormFile file) { if (file == null || file.Length == 0) @@ -263,7 +264,7 @@ public class JtagController : ControllerBase } logger.Info($"Device {address} Upload Bitstream Successfully"); - return TypedResults.Ok("Bitstream Upload Successfully"); + return TypedResults.Ok(true); } /// @@ -272,9 +273,10 @@ public class JtagController : ControllerBase /// 设备地址 /// 设备端口 [HttpPost("DownloadBitstream")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] public async ValueTask DownloadBitstream(string address, int port) { // 检查文件 diff --git a/src/APIClient.ts b/src/APIClient.ts index 0b01edd..49a46e5 100644 --- a/src/APIClient.ts +++ b/src/APIClient.ts @@ -8,9 +8,6 @@ /* eslint-disable */ // ReSharper disable InconsistentNaming -import { batchSetConstraintStates, notifyConstraintChange } from './stores/constraints'; -import type { ConstraintLevel } from './stores/constraints'; - export class Client { private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; private baseUrl: string; @@ -473,7 +470,7 @@ export class JtagClient { * @param address (optional) 设备地址 * @param port (optional) 设备端口 */ - getDeviceIDCode(address: string | undefined, port: number | undefined): Promise { + getDeviceIDCode(address: string | undefined, port: number | undefined): Promise { let url_ = this.baseUrl + "/api/Jtag/GetDeviceIDCode?"; if (address === null) throw new Error("The parameter 'address' cannot be null."); @@ -485,6 +482,61 @@ export class JtagClient { url_ += "port=" + encodeURIComponent("" + port) + "&"; url_ = url_.replace(/[?&]$/, ""); + let options_: RequestInit = { + method: "GET", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processGetDeviceIDCode(_response); + }); + } + + protected processGetDeviceIDCode(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 获取状态寄存器 + * @param address (optional) 设备地址 + * @param port (optional) 设备端口 + */ + readStatusReg(address: string | undefined, port: number | undefined): Promise { + let url_ = this.baseUrl + "/api/Jtag/ReadStatusReg?"; + if (address === null) + throw new Error("The parameter 'address' cannot be null."); + else if (address !== undefined) + url_ += "address=" + encodeURIComponent("" + address) + "&"; + if (port === null) + throw new Error("The parameter 'port' cannot be null."); + else if (port !== undefined) + url_ += "port=" + encodeURIComponent("" + port) + "&"; + url_ = url_.replace(/[?&]$/, ""); + let options_: RequestInit = { method: "GET", headers: { @@ -492,11 +544,11 @@ export class JtagClient { }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processGetDeviceIDCode(_response); + return this.processReadStatusReg(_response); }); } - protected processGetDeviceIDCode(response: Response): Promise { + protected processReadStatusReg(response: Response): Promise { const status = response.status; let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200) { @@ -520,7 +572,7 @@ export class JtagClient { * @param address (optional) 设备地址 * @param file (optional) */ - uploadBitstream(address: string | undefined, file: FileParameter | null | undefined): Promise { + uploadBitstream(address: string | undefined, file: FileParameter | null | undefined): Promise { let url_ = this.baseUrl + "/api/Jtag/UploadBitstream?"; if (address === null) throw new Error("The parameter 'address' cannot be null."); @@ -536,6 +588,7 @@ export class JtagClient { body: content_, method: "POST", headers: { + "Accept": "application/json" } }; @@ -544,7 +597,147 @@ export class JtagClient { }); } - protected processUploadBitstream(response: Response): Promise { + protected processUploadBitstream(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = resultData400 !== undefined ? resultData400 : null; + + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 通过Jtag下载比特流文件 + * @param address (optional) 设备地址 + * @param port (optional) 设备端口 + */ + downloadBitstream(address: string | undefined, port: number | undefined): Promise { + let url_ = this.baseUrl + "/api/Jtag/DownloadBitstream?"; + if (address === null) + throw new Error("The parameter 'address' cannot be null."); + else if (address !== undefined) + url_ += "address=" + encodeURIComponent("" + address) + "&"; + if (port === null) + throw new Error("The parameter 'port' cannot be null."); + else if (port !== undefined) + url_ += "port=" + encodeURIComponent("" + port) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processDownloadBitstream(_response); + }); + } + + protected processDownloadBitstream(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = resultData400 !== undefined ? resultData400 : null; + + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } +} + +export class RemoteUpdaterClient { + private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { + this.http = http ? http : window as any; + this.baseUrl = baseUrl ?? "http://localhost:5000"; + } + + /** + * 上传远程更新比特流文件 + * @param address (optional) 设备地址 + * @param goldenBitream (optional) + * @param bitstream1 (optional) + * @param bitstream2 (optional) + * @param bitstream3 (optional) + * @return 上传结果 + */ + uploadBitstreams(address: string | undefined, goldenBitream: FileParameter | null | undefined, bitstream1: FileParameter | null | undefined, bitstream2: FileParameter | null | undefined, bitstream3: FileParameter | null | undefined): Promise { + let url_ = this.baseUrl + "/api/RemoteUpdater/UploadBitstream?"; + if (address === null) + throw new Error("The parameter 'address' cannot be null."); + else if (address !== undefined) + url_ += "address=" + encodeURIComponent("" + address) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = new FormData(); + if (goldenBitream !== null && goldenBitream !== undefined) + content_.append("goldenBitream", goldenBitream.data, goldenBitream.fileName ? goldenBitream.fileName : "goldenBitream"); + if (bitstream1 !== null && bitstream1 !== undefined) + content_.append("bitstream1", bitstream1.data, bitstream1.fileName ? bitstream1.fileName : "bitstream1"); + if (bitstream2 !== null && bitstream2 !== undefined) + content_.append("bitstream2", bitstream2.data, bitstream2.fileName ? bitstream2.fileName : "bitstream2"); + if (bitstream3 !== null && bitstream3 !== undefined) + content_.append("bitstream3", bitstream3.data, bitstream3.fileName ? bitstream3.fileName : "bitstream3"); + + let options_: RequestInit = { + body: content_, + method: "POST", + headers: { + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processUploadBitstreams(_response); + }); + } + + protected processUploadBitstreams(response: Response): Promise { const status = response.status; let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200) { @@ -567,12 +760,13 @@ export class JtagClient { } /** - * 通过Jtag下载比特流文件 + * 远程更新单个比特流文件 * @param address (optional) 设备地址 * @param port (optional) 设备端口 + * @param bitstreamNum (optional) 比特流位号 */ - downloadBitstream(address: string | undefined, port: number | undefined): Promise { - let url_ = this.baseUrl + "/api/Jtag/DownloadBitstream?"; + updateBitstream(address: string | undefined, port: number | undefined, bitstreamNum: number | undefined): Promise { + let url_ = this.baseUrl + "/api/RemoteUpdater/DownloadBitstream?"; if (address === null) throw new Error("The parameter 'address' cannot be null."); else if (address !== undefined) @@ -581,6 +775,10 @@ export class JtagClient { throw new Error("The parameter 'port' cannot be null."); else if (port !== undefined) url_ += "port=" + encodeURIComponent("" + port) + "&"; + if (bitstreamNum === null) + throw new Error("The parameter 'bitstreamNum' cannot be null."); + else if (bitstreamNum !== undefined) + url_ += "bitstreamNum=" + encodeURIComponent("" + bitstreamNum) + "&"; url_ = url_.replace(/[?&]$/, ""); let options_: RequestInit = { @@ -590,11 +788,11 @@ export class JtagClient { }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processDownloadBitstream(_response); + return this.processUpdateBitstream(_response); }); } - protected processDownloadBitstream(response: Response): Promise { + protected processUpdateBitstream(response: Response): Promise { const status = response.status; let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200) { @@ -619,6 +817,308 @@ export class JtagClient { } return Promise.resolve(null as any); } + + /** + * 下载多个比特流文件 + * @param address (optional) 设备地址 + * @param port (optional) 设备端口 + * @param bitstreamNum (optional) 比特流编号 + * @return 总共上传比特流的数量 + */ + downloadMultiBitstreams(address: string | undefined, port: number | undefined, bitstreamNum: number | null | undefined): Promise { + let url_ = this.baseUrl + "/api/RemoteUpdater/DownloadMultiBitstreams?"; + if (address === null) + throw new Error("The parameter 'address' cannot be null."); + else if (address !== undefined) + url_ += "address=" + encodeURIComponent("" + address) + "&"; + if (port === null) + throw new Error("The parameter 'port' cannot be null."); + else if (port !== undefined) + url_ += "port=" + encodeURIComponent("" + port) + "&"; + if (bitstreamNum !== undefined && bitstreamNum !== null) + url_ += "bitstreamNum=" + encodeURIComponent("" + bitstreamNum) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processDownloadMultiBitstreams(_response); + }); + } + + protected processDownloadMultiBitstreams(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + return; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 热复位比特流文件 + * @param address (optional) 设备地址 + * @param port (optional) 设备端口 + * @param bitstreamNum (optional) 比特流编号 + * @return 操作结果 + */ + hotResetBitstream(address: string | undefined, port: number | undefined, bitstreamNum: number | undefined): Promise { + let url_ = this.baseUrl + "/api/RemoteUpdater/HotResetBitstream?"; + if (address === null) + throw new Error("The parameter 'address' cannot be null."); + else if (address !== undefined) + url_ += "address=" + encodeURIComponent("" + address) + "&"; + if (port === null) + throw new Error("The parameter 'port' cannot be null."); + else if (port !== undefined) + url_ += "port=" + encodeURIComponent("" + port) + "&"; + if (bitstreamNum === null) + throw new Error("The parameter 'bitstreamNum' cannot be null."); + else if (bitstreamNum !== undefined) + url_ += "bitstreamNum=" + encodeURIComponent("" + bitstreamNum) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processHotResetBitstream(_response); + }); + } + + protected processHotResetBitstream(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200) { + return response.text().then((_responseText) => { + return; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ProblemDetails.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + return throwException("A server side error occurred.", status, _responseText, _headers); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } +} + +export class DataClient { + private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { + this.http = http ? http : window as any; + this.baseUrl = baseUrl ?? "http://localhost:5000"; + } + + /** + * 创建数据库表 + * @return 插入的记录数 + */ + createTables(): Promise { + let url_ = this.baseUrl + "/api/Data/CreateTable"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processCreateTables(_response); + }); + } + + protected processCreateTables(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 删除数据库表 + * @return 插入的记录数 + */ + dropTables(): Promise { + let url_ = this.baseUrl + "/api/Data/DropTables"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "DELETE", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processDropTables(_response); + }); + } + + protected processDropTables(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 获取所有用户 + * @return 用户列表 + */ + allUsers(): Promise { + let url_ = this.baseUrl + "/api/Data/AllUsers"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "GET", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processAllUsers(_response); + }); + } + + protected processAllUsers(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + /** + * 注册新用户 + * @param name (optional) 用户名 + * @return 操作结果 + */ + signUpUser(name: string | undefined): Promise { + let url_ = this.baseUrl + "/api/Data/SignUpUser?"; + if (name === null) + throw new Error("The parameter 'name' cannot be null."); + else if (name !== undefined) + url_ += "name=" + encodeURIComponent("" + name) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processSignUpUser(_response); + }); + } + + protected processSignUpUser(response: Response): Promise { + const status = response.status; + let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; + if (status === 200 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } } /** Package options which to send address to read or write */ @@ -687,8 +1187,8 @@ export interface ISendAddrPackOptions { /** Package Burst Type */ export enum BurstType { - ExtendBurst = 0, - FixedBurst = 1, + FixedBurst = 0, + ExtendBurst = 1, } /** UDP接受数据包格式 */ @@ -755,6 +1255,54 @@ export interface IUDPData { hasRead?: boolean; } +export class Exception implements IException { + message?: string; + innerException?: Exception | undefined; + source?: string | undefined; + stackTrace?: string | undefined; + + constructor(data?: IException) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.message = _data["Message"]; + this.innerException = _data["InnerException"] ? Exception.fromJS(_data["InnerException"]) : undefined; + this.source = _data["Source"]; + this.stackTrace = _data["StackTrace"]; + } + } + + static fromJS(data: any): Exception { + data = typeof data === 'object' ? data : {}; + let result = new Exception(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["Message"] = this.message; + data["InnerException"] = this.innerException ? this.innerException.toJSON() : undefined; + data["Source"] = this.source; + data["StackTrace"] = this.stackTrace; + return data; + } +} + +export interface IException { + message?: string; + innerException?: Exception | undefined; + source?: string | undefined; + stackTrace?: string | undefined; +} + export class ProblemDetails implements IProblemDetails { type?: string | undefined; title?: string | undefined; @@ -840,6 +1388,13 @@ export interface FileParameter { fileName: string; } +export interface FileResponse { + data: Blob; + status: number; + fileName?: string; + headers?: { [name: string]: any }; +} + export class ApiException extends Error { message: string; status: number; @@ -869,57 +1424,4 @@ function throwException(message: string, status: number, response: string, heade throw result; else throw new ApiException(message, status, response, headers, null); -} - -// 约束通信相关方法 -export function receiveConstraintUpdates(constraints: Record) { - // 批量更新约束状态 - batchSetConstraintStates(constraints); -} - -export function sendConstraintUpdate(constraint: string, level: ConstraintLevel) { - // 向后端发送约束状态变化 - console.log(`发送约束 ${constraint} 状态变化为 ${level}`); - - // TODO: 实际的WebSocket或HTTP请求发送约束变化 - // 例如: - // socket.emit('constraintUpdate', { constraint, level }); - // 或 - // fetch('/api/constraints', { - // method: 'POST', - // body: JSON.stringify({ constraint, level }), - // headers: { 'Content-Type': 'application/json' } - // }); -} - -// 初始化约束通信 -export function initConstraintCommunication() { - // 监听服务器发来的约束状态变化 - // 示例: - // socket.on('constraintUpdates', (data) => { - // receiveConstraintUpdates(data); - // }); - - // 模拟接收一些初始约束状态 - setTimeout(() => { - receiveConstraintUpdates({ - 'A1': 'high', - 'A2': 'low', - 'A3': 'undefined' - }); - }, 1000); -} - -// 覆盖全局notifyConstraintChange,加入发送逻辑 -const originalNotifyConstraintChange = notifyConstraintChange; -const wrappedNotifyConstraintChange = (constraint: string, level: ConstraintLevel) => { - // 调用原始方法更新本地状态 - originalNotifyConstraintChange(constraint, level); - - // 向后端发送更新 - sendConstraintUpdate(constraint, level); -}; - -// 替换全局方法 -(window as any).__notifyConstraintChange = notifyConstraintChange; -(window as any).notifyConstraintChange = wrappedNotifyConstraintChange; \ No newline at end of file +} \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 85dca44..ff979bf 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,26 +1,34 @@ @@ -40,15 +48,18 @@ provide('theme', {
+
-
+ +

Copyright © 2023 - All right reserved by OurEDA

-
+ + diff --git a/src/components/UploadCard.vue b/src/components/UploadCard.vue index 7d593c2..a8ab95f 100644 --- a/src/components/UploadCard.vue +++ b/src/components/UploadCard.vue @@ -1,48 +1,103 @@ \ No newline at end of file +