feat: can upload medias now

This commit is contained in:
1721518185
2023-12-18 19:31:27 +08:00
parent a958181920
commit 8e7eb90c93
23 changed files with 678 additions and 28 deletions
+2
View File
@@ -51,3 +51,5 @@ Thumbs.db
# api
/api/node_modules
node_modules/
frontend/node_modules/
frontend/dist/
+9 -1
View File
@@ -12,6 +12,7 @@ module.exports = async function (context, req) {
const body = req.body || {};
const page = body.page || 1;
const size = body.size || 10;
const columns = body.columns || false;
let query_conditions = {};
["Name", "Developer", "Distributer"].forEach(key => {
@@ -23,10 +24,17 @@ module.exports = async function (context, req) {
context.log(query_conditions);
const data = await collection.find(query_conditions).skip((page - 1) * size).limit(size).toArray();
const total = await collection.countDocuments(query_conditions);
context.res = {
let response = {
status: 200,
body: { code: 200, total: total, data: data, msg: "SUCCESS" }
};
if (columns) {
const names = await collection.distinct('Name');
response.body.names = names;
}
context.res = response;
} catch (e) {
context.res = {
status: 500,
+19
View File
@@ -0,0 +1,19 @@
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
+64
View File
@@ -0,0 +1,64 @@
const { MongoClient } = require('mongodb');
const connectionString = "mongodb://wecloud:riQjoBDxr09fnyu8yCa9FeP19Op8UNB1ZFVkxEw3a1cQy25YrPnTzHx460TWBp8vaWIm5ciDRGh6ACDbZ5nHeg==@wecloud.mongo.cosmos.azure.com:10255/?ssl=true&retrywrites=false&replicaSet=globaldb&maxIdleTimeMS=120000&appName=@wecloud@"
const client = new MongoClient(connectionString);
const collectionName = "wegame";
const dbName = "wegame";
module.exports = async function (context, req) {
try {
await client.connect();
const db = client.db(dbName);
const gameCollection = db.collection(collectionName);
const gameData = req.body || {};
const necessaryField = "Name";
if (!gameData[necessaryField]) {
context.res = {
status: 400, // Bad Request
body: { code: 400, msg: `Field: [${necessaryField}] is required` }
};
return;
}
const existingGame = await gameCollection.findOne({ "Name": gameData[necessaryField] });
if (existingGame) {
context.res = {
status: 400, // Bad Request
body: { code: 400, msg: `A game with the same title [${gameData[necessaryField]}] already exists` }
};
return;
}
// Convert fields to float where possible
for (const key in gameData) {
if (gameData.hasOwnProperty(key)) {
try {
gameData[key] = parseFloat(gameData[key]);
} catch (e) {
// Keep the original value if it's not a number
}
}
}
// Add timestamps
gameData.date_added = new Date();
gameData.update_time = Date.now();
// Insert the new game data
await gameCollection.insertOne(gameData);
context.res = {
status: 200, // OK
body: { code: 200, msg: "SUCCESS" }
};
} catch (e) {
context.res = {
status: 500, // Internal Server Error
body: { code: 500, msg: `Error: ${e.message}` }
};
} finally {
if (client) {
client.close();
}
}
};
+3
View File
@@ -0,0 +1,3 @@
{
"name": "Azure"
}
+205 -11
View File
@@ -428,6 +428,105 @@
"integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==",
"dev": true
},
"@azure/abort-controller": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
"integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==",
"requires": {
"tslib": "^2.2.0"
}
},
"@azure/core-auth": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/@azure/core-auth/-/core-auth-1.5.0.tgz",
"integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-util": "^1.1.0",
"tslib": "^2.2.0"
}
},
"@azure/core-http": {
"version": "3.0.4",
"resolved": "https://registry.npmmirror.com/@azure/core-http/-/core-http-3.0.4.tgz",
"integrity": "sha512-Fok9VVhMdxAFOtqiiAtg74fL0UJkt0z3D+ouUUxcRLzZNBioPRAMJFVxiWoJljYpXsRi4GDQHzQHDc9AiYaIUQ==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-auth": "^1.3.0",
"@azure/core-tracing": "1.0.0-preview.13",
"@azure/core-util": "^1.1.1",
"@azure/logger": "^1.0.0",
"@types/node-fetch": "^2.5.0",
"@types/tunnel": "^0.0.3",
"form-data": "^4.0.0",
"node-fetch": "^2.6.7",
"process": "^0.11.10",
"tslib": "^2.2.0",
"tunnel": "^0.0.6",
"uuid": "^8.3.0",
"xml2js": "^0.5.0"
}
},
"@azure/core-lro": {
"version": "2.5.4",
"resolved": "https://registry.npmmirror.com/@azure/core-lro/-/core-lro-2.5.4.tgz",
"integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-util": "^1.2.0",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0"
}
},
"@azure/core-paging": {
"version": "1.5.0",
"resolved": "https://registry.npmmirror.com/@azure/core-paging/-/core-paging-1.5.0.tgz",
"integrity": "sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw==",
"requires": {
"tslib": "^2.2.0"
}
},
"@azure/core-tracing": {
"version": "1.0.0-preview.13",
"resolved": "https://registry.npmmirror.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz",
"integrity": "sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==",
"requires": {
"@opentelemetry/api": "^1.0.1",
"tslib": "^2.2.0"
}
},
"@azure/core-util": {
"version": "1.6.1",
"resolved": "https://registry.npmmirror.com/@azure/core-util/-/core-util-1.6.1.tgz",
"integrity": "sha512-h5taHeySlsV9qxuK64KZxy4iln1BtMYlNt5jbuEFN3UFSAd1EwKg/Gjl5a6tZ/W8t6li3xPnutOx7zbDyXnPmQ==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"tslib": "^2.2.0"
}
},
"@azure/logger": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/@azure/logger/-/logger-1.0.4.tgz",
"integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==",
"requires": {
"tslib": "^2.2.0"
}
},
"@azure/storage-blob": {
"version": "12.17.0",
"resolved": "https://registry.npmmirror.com/@azure/storage-blob/-/storage-blob-12.17.0.tgz",
"integrity": "sha512-sM4vpsCpcCApagRW5UIjQNlNylo02my2opgp0Emi8x888hZUvJ3dN69Oq20cEGXkMUWnoCrBaB0zyS3yeB87sQ==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-http": "^3.0.0",
"@azure/core-lro": "^2.2.0",
"@azure/core-paging": "^1.1.1",
"@azure/core-tracing": "1.0.0-preview.13",
"@azure/logger": "^1.0.0",
"events": "^3.0.0",
"tslib": "^2.2.0"
}
},
"@babel/code-frame": {
"version": "7.18.6",
"resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.18.6.tgz",
@@ -1961,6 +2060,11 @@
"which": "^2.0.2"
}
},
"@opentelemetry/api": {
"version": "1.7.0",
"resolved": "https://registry.npmmirror.com/@opentelemetry/api/-/api-1.7.0.tgz",
"integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw=="
},
"@schematics/angular": {
"version": "14.2.9",
"resolved": "https://registry.npmmirror.com/@schematics/angular/-/angular-14.2.9.tgz",
@@ -2113,8 +2217,16 @@
"@types/node": {
"version": "18.11.9",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.11.9.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
"dev": true
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg=="
},
"@types/node-fetch": {
"version": "2.6.9",
"resolved": "https://registry.npmmirror.com/@types/node-fetch/-/node-fetch-2.6.9.tgz",
"integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==",
"requires": {
"@types/node": "*",
"form-data": "^4.0.0"
}
},
"@types/parse-json": {
"version": "4.0.0",
@@ -2168,6 +2280,14 @@
"@types/node": "*"
}
},
"@types/tunnel": {
"version": "0.0.3",
"resolved": "https://registry.npmmirror.com/@types/tunnel/-/tunnel-0.0.3.tgz",
"integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==",
"requires": {
"@types/node": "*"
}
},
"@types/ws": {
"version": "8.5.3",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.3.tgz",
@@ -2560,6 +2680,11 @@
"integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"autoprefixer": {
"version": "10.4.13",
"resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.13.tgz",
@@ -3012,6 +3137,14 @@
"integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
@@ -3480,6 +3613,11 @@
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
"dev": true
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
@@ -3968,8 +4106,7 @@
"events": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"dev": true
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
},
"execa": {
"version": "5.1.1",
@@ -4204,6 +4341,16 @@
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"dev": true
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@@ -5563,14 +5710,12 @@
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"requires": {
"mime-db": "1.52.0"
}
@@ -5849,6 +5994,14 @@
"dev": true,
"optional": true
},
"node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz",
@@ -6807,6 +6960,11 @@
"integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==",
"dev": true
},
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmmirror.com/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -7258,8 +7416,7 @@
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"dev": true
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"schema-utils": {
"version": "2.7.1",
@@ -7965,6 +8122,11 @@
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"dev": true
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/tree-kill/-/tree-kill-1.2.2.tgz",
@@ -7976,6 +8138,11 @@
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmmirror.com/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"type-fest": {
"version": "0.21.3",
"resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz",
@@ -8102,8 +8269,7 @@
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"validate-npm-package-license": {
"version": "3.0.4",
@@ -8164,6 +8330,11 @@
"defaults": "^1.0.3"
}
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"webpack": {
"version": "5.74.0",
"resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.74.0.tgz",
@@ -8383,6 +8554,15 @@
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
"dev": true
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
@@ -8456,6 +8636,20 @@
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"dev": true
},
"xml2js": {
"version": "0.5.0",
"resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
}
},
"xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
},
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
+1
View File
@@ -18,6 +18,7 @@
"@angular/platform-browser": "^14.2.0",
"@angular/platform-browser-dynamic": "^14.2.0",
"@angular/router": "^14.2.0",
"@azure/storage-blob": "^12.17.0",
"ng-zorro-antd": "^14.2.1",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
+5
View File
@@ -17,6 +17,11 @@ const routes: Routes = [
loadChildren: () =>
import('./pages/layout/layout.module').then((m) => m.LayoutModule),
},
{
path:'myUpload',
loadChildren: () =>
import('./pages/myUpload/myUpload.module').then((m) => m.MyUploadModule),
},
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
];
@@ -0,0 +1,27 @@
<div class="upload-section">
<nz-upload
nzType="drag"
[nzMultiple]="true"
[nzBeforeUpload]="beforeUpload"
(nzChange)="handleChange($event)"
class="upload-box">
<p class="ant-upload-drag-icon">
<i nz-icon nzType="inbox"></i>
</p>
<p class="ant-upload-text">Click or drag your videos or photos to this area to upload</p>
<p class="ant-upload-hint">
Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files
</p>
</nz-upload>
<button nz-button nzType="primary" (click)="handleUpload()" [disabled]="uploading">Upload</button>
<nz-spin [nzSpinning]="uploading"></nz-spin>
<!-- if there are files in the fileList and not uploading, show the input and button -->
<div *ngIf="fileList.length > 0 && !uploading">
<input nz-input [(ngModel)]="uploadTitle" placeholder="Please Enter a Title">
<button nz-button nzType="primary" (click)="handleUpload()">Confirm</button>
</div>
<ul>
<li *ngFor="let file of fileList">{{ file.name }}</li>
</ul>
</div>
@@ -0,0 +1,23 @@
::ng-deep .ant-list-vertical .ant-list-item-action > li {
color: #999;
}
.wegame-search {
width: 500px;
margin: 0 auto;
display: block;
margin-bottom: 30px;
}
a {
color: #99a1c8;
}
.card-shadow:hover {
box-shadow: 0 1px 2px -2px #00000029, 0 3px 6px #0000001f,
0 5px 12px 4px #00000017;
}
.text-overflow {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
@@ -0,0 +1,77 @@
import { Component, OnInit } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzUploadChangeParam, NzUploadFile } from 'ng-zorro-antd/upload';
import { BlobServiceClient, ContainerClient } from '@azure/storage-blob';
import { NzModalService } from 'ng-zorro-antd/modal';
@Component({
selector: 'app-file-upload',
templateUrl: './file-upload.component.html',
styleUrls: ['./file-upload.component.scss']
})
export class FileUploadComponent implements OnInit {
uploading = false;
fileList: NzUploadFile[] = [];
uploadTitle = '';
sasUrl = 'https://wecloudblob.blob.core.windows.net/?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2023-12-18T18:13:02Z&st=2023-12-18T10:13:02Z&spr=https,http&sig=pMEPhuudBIztt%2FjWBY%2BWIeGqWHN6BdYMAzUmGSy7PUU%3D';
containerName = 'games';
blobServiceClient: BlobServiceClient;
containerClient: ContainerClient;
constructor(private $message: NzMessageService, private modalService: NzModalService) {
this.blobServiceClient = new BlobServiceClient(this.sasUrl);
this.containerClient = this.blobServiceClient.getContainerClient(this.containerName);
}
ngOnInit(): void {
// Additional initialization logic if required
}
// Handle the file before uploading
beforeUpload = (file: NzUploadFile, _fileList: NzUploadFile[]) => {
this.fileList = this.fileList.concat(file);
return false; // Prevent automatic upload
};
handleUpload(): void {
this.modalService.confirm({
nzTitle: 'Confirm Upload',
nzContent: `Title: ${this.uploadTitle}<br/>Number of files: ${this.fileList.length}`,
nzOnOk: () => this.onConfirmUpload()
});
}
async onConfirmUpload() {
this.uploading = true;
this.uploadTitle = ''; // Reset the title for the next upload
for (const file of this.fileList) {
const blob = new Blob([file as any], { type: file.type });
await this.uploadFileToAzure(this.uploadTitle, file.name, blob);
}
this.fileList = [];
this.uploading = false;
}
handleChange({ file, fileList }: NzUploadChangeParam): void {
const status = file.status;
if (status === 'done') {
this.$message.success(`${file.name} file uploaded successfully.`);
} else if (status === 'error') {
this.$message.error(`${file.name} file upload failed.`);
}
this.fileList = fileList;
}
async uploadFileToAzure(uploadTitle: string, fileName: string, blob: Blob) {
try {
const newFileName = `${uploadTitle}_${fileName}`;
const blockBlobClient = this.containerClient.getBlockBlobClient(newFileName);
await blockBlobClient.uploadData(blob);
this.$message.success(`${fileName} uploaded successfully.`);
} catch (error) {
this.$message.error(`Upload failed: ${error}`);
}
}
}
@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { SharedModule } from '../../shared/shared.module';
import { NzUploadModule } from 'ng-zorro-antd/upload';
import { NzSpinModule } from 'ng-zorro-antd/spin';
import { FileUploadComponent } from './file-upload.component';
@NgModule({
imports: [
CommonModule,
SharedModule,
NzUploadModule,
NzSpinModule,
],
declarations: [FileUploadComponent],
exports: [FileUploadComponent],
})
export class FileUploadModule {}
@@ -20,6 +20,11 @@ const routes: Routes = [
(m) => m.MovieDetailsModule
),
},
{
path: 'myUpload',
loadChildren: () =>
import('../myUpload/myUpload.module').then((m) => m.MyUploadModule),
}
],
},
];
@@ -6,6 +6,9 @@
<li nz-menu-item nzMatchRouter>
<a routerLink="/layout/list">Game Toplist</a>
</li>
<li nz-menu-item nzMatchRouter>
<a routerLink="/layout/myUpload">My Upload</a>
</li>
</ul>
<span class="right-top-tool"
>{{ username
@@ -39,7 +39,7 @@
(click)="isVisible = true"
style="margin-left: 15px"
>
<i nz-icon nzType="plus" nzTheme="outline"></i>Add
<i nz-icon nzType="plus" nzTheme="outline"></i>Add Medias
</button>
</div>
</div>
@@ -60,7 +60,7 @@
text-decoration: underline;
"
(click)="toDetail(item)"
>{{ item.Name }}</a
>{{ item.Name }}</a
>
<span>{{ item.Developer }}</span>
</nz-list-item-meta-title>
@@ -118,24 +118,35 @@
<ng-container *nzModalContent>
<form nz-form [formGroup]="addForm">
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="24" *ngFor="let field of addField">
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="name"
>{{ field.label }}
>Name
</nz-form-label>
<nz-form-control
[nzSm]="14"
[nzXs]="24"
[nzErrorTip]="'Please input ' + field.label!"
[nzErrorTip]="'Please select a name'"
>
<input
<nz-select
nz-input
[formControlName]="field.value"
[formControlName]="addField[0].value"
id="name"
[placeholder]="field.label"
/>
[nzPlaceHolder]="addField[0].value"
nzShowSearch
>
<nz-option
*ngFor="let name of getNamesFromLocalStorage()"
[nzValue]="name"
[nzLabel]="name"
></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<!-- Insert the FileUploadComponent -->
<div nz-col [nzSpan]="24">
<app-file-upload></app-file-upload>
</div>
</div>
</form>
+10 -3
View File
@@ -108,9 +108,12 @@ export class ListComponent implements OnInit {
Distributer: [null],
Developer: [null],
});
this.getWegameList();
this.getWegameList(true);
}
getNamesFromLocalStorage() {
return JSON.parse(localStorage.getItem('names') || '[]');
}
submitForm(): void {
if (this.addForm.valid) {
let params = { ...this.addForm.value };
@@ -152,16 +155,17 @@ export class ListComponent implements OnInit {
return [total, positive];
}
getWegameList() {
getWegameList(columns:boolean = false) {
let params = {
page: this.page,
size: this.size,
columns: columns,
...this.searchForm.value,
};
this.apiService.post('game_list', params).subscribe(
(res: any) => {
this.loading = false;
const { code, data, total } = res;
const { code, data, total, names } = res;
if (code == 200) {
this.loading = false;
this.wegameList = data;
@@ -176,6 +180,9 @@ export class ListComponent implements OnInit {
});
this.total = total;
console.log('this.wegameList', this.wegameList);
if (names) {
localStorage.setItem('names', JSON.stringify(names));
}
} else {
this.wegameList = [];
}
@@ -3,11 +3,15 @@ import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { SharedModule } from '../../shared/shared.module';
import { ListComponent } from './list.component';
import { FileUploadModule } from '../FileUploadComponent/file-upload.module';
import { NzSelectModule } from 'ng-zorro-antd/select'
@NgModule({
imports: [
CommonModule,
SharedModule,
FileUploadModule,
NzSelectModule,
RouterModule.forChild([
{
path: '',
@@ -0,0 +1,128 @@
import { Component, OnInit } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NavigateService } from 'src/app/services/navigate.service';
import { ApiService } from 'src/app/services/api.service';
import { BlobServiceClient, ContainerClient } from '@azure/storage-blob';
import { HttpClient } from '@angular/common/http';
import { lastValueFrom } from 'rxjs';
import { NzModalService } from 'ng-zorro-antd/modal';
import { HttpHeaders } from '@angular/common/http';
@Component({
selector: 'app-favorite',
templateUrl: './myUpload.html',
styleUrls: ['./myUpload.scss'],
})
export class MyUploadComponent implements OnInit {
favoriteList: any = [];
loading: boolean = true;
username: any;
images: {
url: any,
type: any,
uploadTime:any,
blobUrl:any ,
picTitle:any
}[] = [];
// Azure Storage SAS URL
sasUrl = 'https://wecloudblob.blob.core.windows.net/?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2023-12-18T18:13:02Z&st=2023-12-18T10:13:02Z&spr=https,http&sig=pMEPhuudBIztt%2FjWBY%2BWIeGqWHN6BdYMAzUmGSy7PUU%3D';
// sasToken = 'si=asset&sv=2022-11-02&sr=c&sig=OA8DpIpkl1ak4ZG%2BA7BzMtIRbI6carOTxLtzAcHa9pg%3D'
constructor(
private apiService: ApiService,
private $message: NzMessageService,
private navigateService: NavigateService,
private http: HttpClient,
private modalService: NzModalService
) {}
ngOnInit() {
this.username = localStorage.getItem('username') as any;
this.loadImagesFromAzure();
}
private extractSasToken(): string {
// Extract the SAS token from your sasUrl
const sasToken = this.sasUrl.split('?')[1];
return sasToken ? `?${sasToken}` : '';
}
previewImage(image: { url: string, type: string }) {
let content = '';
if (image.type.startsWith('image')) {
content = `<img src="${image.url}" alt="Image" style="width: 100%; max-height: 600px;">`;
} else if (image.type.startsWith('video')) {
content = `<video src="${image.url}" controls style="width: 100%; max-height: 600px;"></video>`;
}else if (image.type.startsWith('audio')) {
content = `<audio src="${image.url}" controls style="width: 100%; max-height: 600px;"></video>`;
}
else {
// Handle other types as needed
}
this.modalService.create({
nzTitle: 'Preview',
nzContent: content,
nzFooter: null
});
}
downloadImage(url: string) {
window.location.href = url;
}
async deleteImage(index: number) {
const image = this.images[index];
const blobUrl = image.blobUrl; // Assuming this is the URL of the blob
const headers = new HttpHeaders({
'x-ms-date': new Date().toUTCString(),
'x-ms-version': '2022-11-02' // Use the version of Azure Storage Service you are using
});
try {
await this.http.delete(blobUrl, { headers }).toPromise();
// After the image is successfully deleted from Azure, remove it from the images array
this.images.splice(index, 1);
} catch (error) {
console.error('Failed to delete blob:', error);
}
}
async loadImagesFromAzure() {
const containerUrl = 'https://medias.blob.core.windows.net/games';
const query = '?restype=container&comp=list'; // SAS token
const fullUrl = `${containerUrl}${query}`;
try {
const response = await lastValueFrom(this.http.get(fullUrl, { responseType: 'text' }));
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(response, 'text/xml');
const blobs = xmlDoc.getElementsByTagName('Blob');
this.images = [];
for (let i = 0; i < blobs.length; i++) {
const blob = blobs[i];
const name = blob.getElementsByTagName('Name')[0].textContent || '';
const title = JSON.parse(localStorage.getItem('gameInfo') as any).Title;
const lastModified = blob.getElementsByTagName('Last-Modified')[0].textContent || '';
if (!name || name.includes(this.username)) {
// const blobUrl = `${containerUrl}/${name}${this.extractSasToken()}}`;
const url = blob.getElementsByTagName('Url')[0].textContent || '';
const blobUrl = `${containerUrl}/${name}${this.extractSasToken()}`;
const picTitle = name.split('_')[0].replace('assets/', '');
// Assuming you want to display images
this.images.push({
url: url,
type: 'image/jpeg',
uploadTime: lastModified ,
blobUrl: blobUrl,
picTitle: picTitle
}); // Modify 'type' as needed
}
}
} catch (error) {
console.error('Error fetching blobs:', error);
}
}
}
@@ -0,0 +1,16 @@
<h2>Upload Count({{images.length}})</h2>
<nz-list [nzDataSource]="images" nzBordered>
<nz-list-item *ngFor="let image of images; let i = index">
<nz-list-item-meta
[nzAvatar]="image.url"
[nzTitle]="'Upload by ' + username"
[nzDescription]="image.uploadTime">
<p>{{ image.picTitle }}</p>
<a [href]="image.url" target="_blank">{{ image.url }}</a>
</nz-list-item-meta>
<button nz-button nzType="primary" [ngStyle]="{ marginRight: '10px' }" (click)="previewImage(image)">Preview</button>
<button nz-button nzType="primary" [ngStyle]="{ marginRight: '10px' }" (click)="downloadImage(image.url)">Download</button>
<button nz-button nzType="primary" nzDanger (click)="deleteImage(i)">Delete</button>
</nz-list-item>
</nz-list>
@@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { SharedModule } from '../../shared/shared.module';
import { MyUploadComponent } from './myUpload.component';
// import {FormatTimePipe} from "../../../pipe/formatTime.pipe";
@NgModule({
imports: [
CommonModule,
SharedModule,
RouterModule.forChild([
{
path: '',
component: MyUploadComponent,
},
]),
],
declarations: [MyUploadComponent],
exports: [MyUploadComponent],
})
export class MyUploadModule {}
@@ -0,0 +1,11 @@
.music-search {
width: 500px;
margin: 0 auto;
display: block;
margin-bottom: 30px;
}
.nz-avatar {
width: 80px;
height: 80px;
}
-3
View File
@@ -1,3 +0,0 @@
## Start my azure cloud applocation
- Test in local: `swa start frontend/dist/ng_front --api-location api`
+4
View File
@@ -0,0 +1,4 @@
## Start my azure cloud applocation
- WebUrl: `https://wonderful-desert-071333900.4.azurestaticapps.net`
- Github: `https://github.com/1721518185/WeCloud/tree/main`
- Test in local: `swa start frontend/dist/ng_front --api-location api`