47 changed files with 1180 additions and 572 deletions
@ -1,15 +0,0 @@ |
|||||
# Test Server |
|
||||
|
|
||||
It is used to start the test interface service, which can test the upload, websocket, login and other interfaces. |
|
||||
|
|
||||
## Usage |
|
||||
|
|
||||
```bash |
|
||||
|
|
||||
cd ./test/server |
|
||||
|
|
||||
pnpm install |
|
||||
|
|
||||
pnpm run start |
|
||||
|
|
||||
``` |
|
@ -1,18 +0,0 @@ |
|||||
import FileService from '../service/FileService'; |
|
||||
|
|
||||
class FileController { |
|
||||
private service: FileService = new FileService(); |
|
||||
|
|
||||
upload = async (ctx) => { |
|
||||
const files = ctx.request.files.file; |
|
||||
console.log(files); |
|
||||
|
|
||||
if (files.length === undefined) { |
|
||||
this.service.upload(ctx, files, false); |
|
||||
} else { |
|
||||
this.service.upload(ctx, files, true); |
|
||||
} |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default new FileController(); |
|
@ -1,15 +0,0 @@ |
|||||
import UserService from '../service/UserService'; |
|
||||
|
|
||||
class UserController { |
|
||||
private service: UserService = new UserService(); |
|
||||
|
|
||||
login = async (ctx) => { |
|
||||
ctx.body = await this.service.login(); |
|
||||
}; |
|
||||
|
|
||||
getUserInfoById = async (ctx) => { |
|
||||
ctx.body = await this.service.getUserInfoById(); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default new UserController(); |
|
@ -1,18 +0,0 @@ |
|||||
const { name } = require('./package.json'); |
|
||||
const path = require('path'); |
|
||||
|
|
||||
module.exports = { |
|
||||
apps: [ |
|
||||
{ |
|
||||
name, |
|
||||
script: path.resolve(__dirname, './dist/index.js'), |
|
||||
instances: require('os').cpus().length, |
|
||||
autorestart: true, |
|
||||
watch: true, |
|
||||
env_production: { |
|
||||
NODE_ENV: 'production', |
|
||||
PORT: 8080, |
|
||||
}, |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
@ -1,63 +0,0 @@ |
|||||
import Koa from 'koa'; |
|
||||
import path from 'path'; |
|
||||
import Router from 'koa-router'; |
|
||||
import body from 'koa-body'; |
|
||||
import cors from 'koa2-cors'; |
|
||||
import koaStatic from 'koa-static'; |
|
||||
import websockify from 'koa-websocket'; |
|
||||
import route from 'koa-route'; |
|
||||
|
|
||||
import AppRoutes from './routes'; |
|
||||
|
|
||||
const PORT = 3300; |
|
||||
|
|
||||
const app = websockify(new Koa()); |
|
||||
|
|
||||
app.ws.use(function (ctx, next) { |
|
||||
ctx.websocket.send('connection succeeded!'); |
|
||||
return next(ctx); |
|
||||
}); |
|
||||
|
|
||||
app.ws.use( |
|
||||
route.all('/test', function (ctx) { |
|
||||
// ctx.websocket.send('Hello World');
|
|
||||
ctx.websocket.on('message', function (message) { |
|
||||
// do something with the message from client
|
|
||||
|
|
||||
if (message !== 'ping') { |
|
||||
const data = JSON.stringify({ |
|
||||
id: Math.ceil(Math.random() * 1000), |
|
||||
time: new Date().getTime(), |
|
||||
res: `${message}`, |
|
||||
}); |
|
||||
ctx.websocket.send(data); |
|
||||
} |
|
||||
console.log(message); |
|
||||
}); |
|
||||
}), |
|
||||
); |
|
||||
|
|
||||
const router = new Router(); |
|
||||
|
|
||||
// router
|
|
||||
AppRoutes.forEach((route) => router[route.method](route.path, route.action)); |
|
||||
|
|
||||
app.use(cors()); |
|
||||
app.use( |
|
||||
body({ |
|
||||
encoding: 'gzip', |
|
||||
multipart: true, |
|
||||
formidable: { |
|
||||
// uploadDir: path.join(__dirname, '/upload/'), // 设置文件上传目录
|
|
||||
keepExtensions: true, |
|
||||
maxFieldsSize: 20 * 1024 * 1024, |
|
||||
}, |
|
||||
}), |
|
||||
); |
|
||||
app.use(router.routes()); |
|
||||
app.use(router.allowedMethods()); |
|
||||
app.use(koaStatic(path.join(__dirname))); |
|
||||
|
|
||||
app.listen(PORT, () => { |
|
||||
console.log(`Application started successfully: http://localhost:${PORT}`); |
|
||||
}); |
|
@ -1,8 +0,0 @@ |
|||||
{ |
|
||||
"watch": ["src"], |
|
||||
"ext": "ts", |
|
||||
"exec": "ts-node -r tsconfig-paths/register index.ts", |
|
||||
"events": { |
|
||||
"restart": "clear" |
|
||||
} |
|
||||
} |
|
@ -1,36 +0,0 @@ |
|||||
{ |
|
||||
"name": "server", |
|
||||
"version": "1.0.0", |
|
||||
"license": "MIT", |
|
||||
"scripts": { |
|
||||
"compile": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ", |
|
||||
"prod": "npx pm2 start ecosystem.config.js --env production", |
|
||||
"restart": "pm2 restart ecosystem.config.js --env production", |
|
||||
"start": "nodemon", |
|
||||
"stop": "npx pm2 stop ecosystem.config.js" |
|
||||
}, |
|
||||
"dependencies": { |
|
||||
"fs-extra": "^11.1.1", |
|
||||
"koa": "^2.14.2", |
|
||||
"koa-body": "^6.0.1", |
|
||||
"koa-bodyparser": "^4.4.1", |
|
||||
"koa-route": "^3.2.0", |
|
||||
"koa-router": "^12.0.0", |
|
||||
"koa-static": "^5.0.0", |
|
||||
"koa-websocket": "^7.0.0", |
|
||||
"koa2-cors": "^2.0.6" |
|
||||
}, |
|
||||
"devDependencies": { |
|
||||
"@types/koa": "^2.13.6", |
|
||||
"@types/koa-bodyparser": "^5.0.2", |
|
||||
"@types/koa-router": "^7.4.4", |
|
||||
"@types/node": "^20.4.0", |
|
||||
"nodemon": "^2.0.22", |
|
||||
"pm2": "^5.3.0", |
|
||||
"rimraf": "^5.0.1", |
|
||||
"ts-node": "^10.9.1", |
|
||||
"tsconfig-paths": "^4.2.0", |
|
||||
"tsup": "^7.1.0", |
|
||||
"typescript": "^5.1.6" |
|
||||
} |
|
||||
} |
|
@ -1,23 +0,0 @@ |
|||||
import UserController from './controller/UserController'; |
|
||||
import FileController from './controller/FileController'; |
|
||||
|
|
||||
export default [ |
|
||||
// user
|
|
||||
{ |
|
||||
path: '/login', |
|
||||
method: 'post', |
|
||||
action: UserController.login, |
|
||||
}, |
|
||||
{ |
|
||||
path: '/getUserInfoById', |
|
||||
method: 'get', |
|
||||
action: UserController.getUserInfoById, |
|
||||
}, |
|
||||
|
|
||||
// file
|
|
||||
{ |
|
||||
path: '/upload', |
|
||||
method: 'post', |
|
||||
action: FileController.upload, |
|
||||
}, |
|
||||
]; |
|
@ -1,54 +0,0 @@ |
|||||
import path from 'path'; |
|
||||
import fs from 'fs-extra'; |
|
||||
|
|
||||
const uploadUrl = 'http://localhost:3300/static/upload'; |
|
||||
const filePath = path.join(__dirname, '../static/upload/'); |
|
||||
|
|
||||
fs.ensureDir(filePath); |
|
||||
export default class UserService { |
|
||||
async upload(ctx, files, isMultiple) { |
|
||||
let fileReader, fileResource, writeStream; |
|
||||
|
|
||||
const fileFunc = function (file) { |
|
||||
fileReader = fs.createReadStream(file.path); |
|
||||
fileResource = filePath + `/${file.name}`; |
|
||||
console.log(fileResource); |
|
||||
|
|
||||
writeStream = fs.createWriteStream(fileResource); |
|
||||
fileReader.pipe(writeStream); |
|
||||
}; |
|
||||
|
|
||||
const returnFunc = function (flag) { |
|
||||
if (flag) { |
|
||||
let url = ''; |
|
||||
for (let i = 0; i < files.length; i++) { |
|
||||
url += uploadUrl + `/${files[i].name},`; |
|
||||
} |
|
||||
url = url.replace(/,$/gi, ''); |
|
||||
ctx.body = { |
|
||||
url: url, |
|
||||
code: 0, |
|
||||
message: 'upload Success!', |
|
||||
}; |
|
||||
} else { |
|
||||
ctx.body = { |
|
||||
url: uploadUrl + `/${files.name}`, |
|
||||
code: 0, |
|
||||
message: 'upload Success!', |
|
||||
}; |
|
||||
} |
|
||||
}; |
|
||||
console.log(isMultiple, files.length); |
|
||||
|
|
||||
if (isMultiple) { |
|
||||
for (let i = 0; i < files.length; i++) { |
|
||||
const f1 = files[i]; |
|
||||
fileFunc(f1); |
|
||||
} |
|
||||
} else { |
|
||||
fileFunc(files); |
|
||||
} |
|
||||
fs.ensureDir(filePath); |
|
||||
returnFunc(isMultiple); |
|
||||
} |
|
||||
} |
|
@ -1,25 +0,0 @@ |
|||||
import { Result } from '../utils'; |
|
||||
|
|
||||
const fakeUserInfo = { |
|
||||
userId: '1', |
|
||||
username: 'vben', |
|
||||
realName: 'Vben Admin', |
|
||||
desc: 'manager', |
|
||||
password: '123456', |
|
||||
token: 'fakeToken1', |
|
||||
roles: [ |
|
||||
{ |
|
||||
roleName: 'Super Admin', |
|
||||
value: 'super', |
|
||||
}, |
|
||||
], |
|
||||
}; |
|
||||
export default class UserService { |
|
||||
async login() { |
|
||||
return Result.success(fakeUserInfo); |
|
||||
} |
|
||||
|
|
||||
async getUserInfoById() { |
|
||||
return Result.success(fakeUserInfo); |
|
||||
} |
|
||||
} |
|
@ -1,7 +0,0 @@ |
|||||
{ |
|
||||
"$schema": "https://json.schemastore.org/tsconfig", |
|
||||
"extends": "@vben/ts-config/node-server.json", |
|
||||
"compilerOptions": { |
|
||||
"noImplicitAny": false |
|
||||
} |
|
||||
} |
|
@ -1,9 +0,0 @@ |
|||||
export class Result { |
|
||||
static success(data: any) { |
|
||||
return { |
|
||||
code: 0, |
|
||||
success: true, |
|
||||
result: data, |
|
||||
}; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,241 @@ |
|||||
|
(function (global, factory) { |
||||
|
typeof exports === 'object' && typeof module !== 'undefined' |
||||
|
? (module.exports = factory(global)) |
||||
|
: typeof define === 'function' && define.amd |
||||
|
? define(factory) |
||||
|
: factory(global); |
||||
|
})( |
||||
|
typeof self !== 'undefined' |
||||
|
? self |
||||
|
: typeof window !== 'undefined' |
||||
|
? window |
||||
|
: typeof global !== 'undefined' |
||||
|
? global |
||||
|
: this, |
||||
|
function (global) { |
||||
|
global = global || {}; |
||||
|
var _Base64 = global.Base64; |
||||
|
var version = '2.6.3'; |
||||
|
var b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
||||
|
var b64tab = (function (bin) { |
||||
|
var t = {}; |
||||
|
for (var i = 0, l = bin.length; i < l; i++) { |
||||
|
t[bin.charAt(i)] = i; |
||||
|
} |
||||
|
return t; |
||||
|
})(b64chars); |
||||
|
var fromCharCode = String.fromCharCode; |
||||
|
var cb_utob = function (c) { |
||||
|
if (c.length < 2) { |
||||
|
var cc = c.charCodeAt(0); |
||||
|
return cc < 128 |
||||
|
? c |
||||
|
: cc < 2048 |
||||
|
? fromCharCode(192 | (cc >>> 6)) + fromCharCode(128 | (cc & 63)) |
||||
|
: fromCharCode(224 | ((cc >>> 12) & 15)) + |
||||
|
fromCharCode(128 | ((cc >>> 6) & 63)) + |
||||
|
fromCharCode(128 | (cc & 63)); |
||||
|
} else { |
||||
|
var cc = 65536 + (c.charCodeAt(0) - 55296) * 1024 + (c.charCodeAt(1) - 56320); |
||||
|
return ( |
||||
|
fromCharCode(240 | ((cc >>> 18) & 7)) + |
||||
|
fromCharCode(128 | ((cc >>> 12) & 63)) + |
||||
|
fromCharCode(128 | ((cc >>> 6) & 63)) + |
||||
|
fromCharCode(128 | (cc & 63)) |
||||
|
); |
||||
|
} |
||||
|
}; |
||||
|
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g; |
||||
|
var utob = function (u) { |
||||
|
return u.replace(re_utob, cb_utob); |
||||
|
}; |
||||
|
var cb_encode = function (ccc) { |
||||
|
var padlen = [0, 2, 1][ccc.length % 3], |
||||
|
ord = |
||||
|
(ccc.charCodeAt(0) << 16) | |
||||
|
((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8) | |
||||
|
(ccc.length > 2 ? ccc.charCodeAt(2) : 0), |
||||
|
chars = [ |
||||
|
b64chars.charAt(ord >>> 18), |
||||
|
b64chars.charAt((ord >>> 12) & 63), |
||||
|
padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63), |
||||
|
padlen >= 1 ? '=' : b64chars.charAt(ord & 63), |
||||
|
]; |
||||
|
return chars.join(''); |
||||
|
}; |
||||
|
var btoa = |
||||
|
global.btoa && typeof global.btoa == 'function' |
||||
|
? function (b) { |
||||
|
return global.btoa(b); |
||||
|
} |
||||
|
: function (b) { |
||||
|
if (b.match(/[^\x00-\xFF]/)) { |
||||
|
throw new RangeError('The string contains invalid characters.'); |
||||
|
} |
||||
|
return b.replace(/[\s\S]{1,3}/g, cb_encode); |
||||
|
}; |
||||
|
var _encode = function (u) { |
||||
|
return btoa(utob(String(u))); |
||||
|
}; |
||||
|
var mkUriSafe = function (b64) { |
||||
|
return b64 |
||||
|
.replace(/[+\/]/g, function (m0) { |
||||
|
return m0 == '+' ? '-' : '_'; |
||||
|
}) |
||||
|
.replace(/=/g, ''); |
||||
|
}; |
||||
|
var encode = function (u, urisafe) { |
||||
|
return urisafe ? mkUriSafe(_encode(u)) : _encode(u); |
||||
|
}; |
||||
|
var encodeURI = function (u) { |
||||
|
return encode(u, true); |
||||
|
}; |
||||
|
var fromUint8Array; |
||||
|
if (global.Uint8Array) { |
||||
|
fromUint8Array = function (a, urisafe) { |
||||
|
var b64 = ''; |
||||
|
for (var i = 0, l = a.length; i < l; i += 3) { |
||||
|
var a0 = a[i], |
||||
|
a1 = a[i + 1], |
||||
|
a2 = a[i + 2]; |
||||
|
var ord = (a0 << 16) | (a1 << 8) | a2; |
||||
|
b64 += |
||||
|
b64chars.charAt(ord >>> 18) + |
||||
|
b64chars.charAt((ord >>> 12) & 63) + |
||||
|
(typeof a1 != 'undefined' ? b64chars.charAt((ord >>> 6) & 63) : '=') + |
||||
|
(typeof a2 != 'undefined' ? b64chars.charAt(ord & 63) : '='); |
||||
|
} |
||||
|
return urisafe ? mkUriSafe(b64) : b64; |
||||
|
}; |
||||
|
} |
||||
|
var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g; |
||||
|
var cb_btou = function (cccc) { |
||||
|
switch (cccc.length) { |
||||
|
case 4: |
||||
|
var cp = |
||||
|
((7 & cccc.charCodeAt(0)) << 18) | |
||||
|
((63 & cccc.charCodeAt(1)) << 12) | |
||||
|
((63 & cccc.charCodeAt(2)) << 6) | |
||||
|
(63 & cccc.charCodeAt(3)), |
||||
|
offset = cp - 65536; |
||||
|
return fromCharCode((offset >>> 10) + 55296) + fromCharCode((offset & 1023) + 56320); |
||||
|
case 3: |
||||
|
return fromCharCode( |
||||
|
((15 & cccc.charCodeAt(0)) << 12) | |
||||
|
((63 & cccc.charCodeAt(1)) << 6) | |
||||
|
(63 & cccc.charCodeAt(2)), |
||||
|
); |
||||
|
default: |
||||
|
return fromCharCode(((31 & cccc.charCodeAt(0)) << 6) | (63 & cccc.charCodeAt(1))); |
||||
|
} |
||||
|
}; |
||||
|
var btou = function (b) { |
||||
|
return b.replace(re_btou, cb_btou); |
||||
|
}; |
||||
|
var cb_decode = function (cccc) { |
||||
|
var len = cccc.length, |
||||
|
padlen = len % 4, |
||||
|
n = |
||||
|
(len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0) | |
||||
|
(len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0) | |
||||
|
(len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0) | |
||||
|
(len > 3 ? b64tab[cccc.charAt(3)] : 0), |
||||
|
chars = [fromCharCode(n >>> 16), fromCharCode((n >>> 8) & 255), fromCharCode(n & 255)]; |
||||
|
chars.length -= [0, 0, 2, 1][padlen]; |
||||
|
return chars.join(''); |
||||
|
}; |
||||
|
var _atob = |
||||
|
global.atob && typeof global.atob == 'function' |
||||
|
? function (a) { |
||||
|
return global.atob(a); |
||||
|
} |
||||
|
: function (a) { |
||||
|
return a.replace(/\S{1,4}/g, cb_decode); |
||||
|
}; |
||||
|
var atob = function (a) { |
||||
|
return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, '')); |
||||
|
}; |
||||
|
var _decode = function (a) { |
||||
|
return btou(_atob(a)); |
||||
|
}; |
||||
|
var _fromURI = function (a) { |
||||
|
return String(a) |
||||
|
.replace(/[-_]/g, function (m0) { |
||||
|
return m0 == '-' ? '+' : '/'; |
||||
|
}) |
||||
|
.replace(/[^A-Za-z0-9\+\/]/g, ''); |
||||
|
}; |
||||
|
var decode = function (a) { |
||||
|
return _decode(_fromURI(a)); |
||||
|
}; |
||||
|
var toUint8Array; |
||||
|
if (global.Uint8Array) { |
||||
|
toUint8Array = function (a) { |
||||
|
return Uint8Array.from(atob(_fromURI(a)), function (c) { |
||||
|
return c.charCodeAt(0); |
||||
|
}); |
||||
|
}; |
||||
|
} |
||||
|
var noConflict = function () { |
||||
|
var Base64 = global.Base64; |
||||
|
global.Base64 = _Base64; |
||||
|
return Base64; |
||||
|
}; |
||||
|
global.Base64 = { |
||||
|
VERSION: version, |
||||
|
atob: atob, |
||||
|
btoa: btoa, |
||||
|
fromBase64: decode, |
||||
|
toBase64: encode, |
||||
|
utob: utob, |
||||
|
encode: encode, |
||||
|
encodeURI: encodeURI, |
||||
|
btou: btou, |
||||
|
decode: decode, |
||||
|
noConflict: noConflict, |
||||
|
fromUint8Array: fromUint8Array, |
||||
|
toUint8Array: toUint8Array, |
||||
|
}; |
||||
|
if (typeof Object.defineProperty === 'function') { |
||||
|
var noEnum = function (v) { |
||||
|
return { value: v, enumerable: false, writable: true, configurable: true }; |
||||
|
}; |
||||
|
global.Base64.extendString = function () { |
||||
|
Object.defineProperty( |
||||
|
String.prototype, |
||||
|
'fromBase64', |
||||
|
noEnum(function () { |
||||
|
return decode(this); |
||||
|
}), |
||||
|
); |
||||
|
Object.defineProperty( |
||||
|
String.prototype, |
||||
|
'toBase64', |
||||
|
noEnum(function (urisafe) { |
||||
|
return encode(this, urisafe); |
||||
|
}), |
||||
|
); |
||||
|
Object.defineProperty( |
||||
|
String.prototype, |
||||
|
'toBase64URI', |
||||
|
noEnum(function () { |
||||
|
return encode(this, true); |
||||
|
}), |
||||
|
); |
||||
|
}; |
||||
|
} |
||||
|
if (global['Meteor']) { |
||||
|
Base64 = global.Base64; |
||||
|
} |
||||
|
if (typeof module !== 'undefined' && module.exports) { |
||||
|
module.exports.Base64 = global.Base64; |
||||
|
} else { |
||||
|
if (typeof define === 'function' && define.amd) { |
||||
|
define([], function () { |
||||
|
return global.Base64; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
return { Base64: global.Base64 }; |
||||
|
}, |
||||
|
); |
@ -1,45 +1,70 @@ |
|||||
<template> |
<template> |
||||
<BasicModal v-bind="$attrs" @register="registerModal" width="1200px" :showOkBtn="false" :title="processName"> |
<BasicModal |
||||
<initiatesProjectsApproval :record="record" @close="exit" v-if="record.stage=='creatProjectinfo'"/> |
v-bind="$attrs" |
||||
|
@register="registerModal" |
||||
|
width="1200px" |
||||
|
:showOkBtn="false" |
||||
|
:title="processName" |
||||
|
> |
||||
|
<initiatesProjectsApproval |
||||
|
:record="record" |
||||
|
@close="exit" |
||||
|
v-if="record.stage == 'creatProjectinfo'" |
||||
|
/> |
||||
<uploadfileApproval :record="record" @close="exit" v-if="record.stage == 'supervisionFile'" /> |
<uploadfileApproval :record="record" @close="exit" v-if="record.stage == 'supervisionFile'" /> |
||||
<projectPlanApproval :record="record" @close="exit" v-if="record.stage == 'createPlaninfo'" /> |
<projectPlanApproval :record="record" @close="exit" v-if="record.stage == 'createPlaninfo'" /> |
||||
<planFileApproval :record="record" @close="exit" v-if="planfileNames.includes(record.stage)" /> |
<planFileApproval :record="record" @close="exit" v-if="planfileNames.includes(record.stage)" /> |
||||
<fieldChangeApproval :record="record" @close="exit" v-if="record.stage == 'fieldChange'" /> |
<fieldChangeApproval :record="record" @close="exit" v-if="record.stage == 'fieldChange'" /> |
||||
<contractApproval :record="record" @close="exit" v-if="record.stage == 'createContract'" /> |
<contractApproval :record="record" @close="exit" v-if="record.stage == 'createContract'" /> |
||||
<uploadURTfileApproval :record="record" @close="exit" v-if="record.stage=='createURT'||record.stage=='createURT2'"/> |
<uploadURTfileApproval |
||||
|
:record="record" |
||||
|
@close="exit" |
||||
|
v-if="record.stage == 'createURT' || record.stage == 'createURT2'" |
||||
|
/> |
||||
<MergeProjectApprova :record="record" @close="exit" v-if="record.stage == 'MergeProject'" /> |
<MergeProjectApprova :record="record" @close="exit" v-if="record.stage == 'MergeProject'" /> |
||||
<SplitProjectApprova :record="record" @close="exit" v-if="record.stage == 'SplitProject'" /> |
<SplitProjectApprova :record="record" @close="exit" v-if="record.stage == 'SplitProject'" /> |
||||
</BasicModal> |
</BasicModal> |
||||
</template> |
</template> |
||||
<script lang="ts" name="ApprovalPageModel" setup> |
<script lang="ts" name="ApprovalPageModel" setup> |
||||
import {ref} from "vue" |
import { ref } from 'vue'; |
||||
import { BasicModal, useModalInner } from '@/components/Modal'; |
import { BasicModal, useModalInner } from '@/components/Modal'; |
||||
|
|
||||
import initiatesProjectsApproval from "../initiatesProjectsApproval.vue" |
import initiatesProjectsApproval from '../initiatesProjectsApproval.vue'; |
||||
import planFileApproval from '@/views/ProcessApprovalSubPage/planFileApproval.vue' |
import planFileApproval from '@/views/ProcessApprovalSubPage/planFileApproval.vue'; |
||||
import uploadfileApproval from '../uploadfileApproval.vue' |
import uploadfileApproval from '../uploadfileApproval.vue'; |
||||
import projectPlanApproval from '../projectPlanApproval.vue' |
import projectPlanApproval from '../projectPlanApproval.vue'; |
||||
import fieldChangeApproval from '../fieldChangeApproval.vue' |
import fieldChangeApproval from '../fieldChangeApproval.vue'; |
||||
import contractApproval from '../contractApproval.vue' |
import contractApproval from '../contractApproval.vue'; |
||||
import uploadURTfileApproval from '../uploadURTfileApproval.vue' |
import uploadURTfileApproval from '../uploadURTfileApproval.vue'; |
||||
import MergeProjectApprova from '../MergeProjectApprova.vue' |
import MergeProjectApprova from '../MergeProjectApprova.vue'; |
||||
import SplitProjectApprova from '../SplitProjectApprova.vue' |
import SplitProjectApprova from '../SplitProjectApprova.vue'; |
||||
|
|
||||
const planfileNames = ["projectApprovalStage","feasibilityTechReviewConfirm","finalFeasibilityReportDraft","centralizedCheck","createPlaninfoFile","bidDocumentsPreparation","costEvalReportConfirm"] |
const planfileNames = [ |
||||
|
'projectApprovalStage', |
||||
|
'feasibilityTechReviewConfirm', |
||||
|
'finalFeasibilityReportDraft', |
||||
|
'centralizedCheck', |
||||
|
'createPlaninfoFile', |
||||
|
'bidDocumentsPreparation', |
||||
|
'costEvalReportConfirm', |
||||
|
"chuBuSheJiShenPi", |
||||
|
"zhongYanJieDuan", |
||||
|
"chuYanJieDuan", |
||||
|
"shouFuZhiFu", |
||||
|
"heTongQianDing" |
||||
|
]; |
||||
const [registerModal, { closeModal }] = useModalInner(init); |
const [registerModal, { closeModal }] = useModalInner(init); |
||||
defineProps(["record"]) |
defineProps(['record']); |
||||
|
|
||||
let processName= ref() |
let processName = ref(); |
||||
let emit = defineEmits(["close"]) |
let emit = defineEmits(['close']); |
||||
function exit() { |
function exit() { |
||||
closeModal() |
closeModal(); |
||||
console.log("ApprovalPageModel") |
console.log('ApprovalPageModel'); |
||||
emit("close") |
emit('close'); |
||||
} |
} |
||||
function init(initData) { |
function init(initData) { |
||||
processName.value=initData.record.processName |
processName.value = initData.record.processName; |
||||
} |
} |
||||
|
|
||||
</script> |
</script> |
||||
<style></style> |
<style></style> |
||||
|
|
@ -0,0 +1,262 @@ |
|||||
|
<template> |
||||
|
<PageWrapper dense> |
||||
|
<!--引用表格--> |
||||
|
<div> |
||||
|
<a-tabs v-model:activeKey="activeKey" type="card" @change="handleTabChange"> |
||||
|
<a-tab-pane key="1" tab="入库项目汇总(按任务)"> |
||||
|
<BasicTable @register="registerRenwuTable"> |
||||
|
<template #toolbar> |
||||
|
<div class="text-base font-bold">单位:(万元)</div> |
||||
|
<a-button type="primary" @click="showMore('renwu')" shape="round">更多</a-button> |
||||
|
</template> |
||||
|
<template #headerTop> |
||||
|
<div class="container mx-auto mt-4 mb-4 h-20"> |
||||
|
<div class="grid grid-cols-4 gap-4 h-full"> |
||||
|
<div class="bg-[#1890FF] opacity-100 h-full"> |
||||
|
<div class="grid grid-cols-4 gap-1 h-full"> |
||||
|
<div class="col-span-3 mt-4 ml-4 text-white">项目数量</div> |
||||
|
<div |
||||
|
class="col-span-1 flex justify-center items-center text-white text-4xl font-bold " |
||||
|
>{{ planSummary.projectNum }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="bg-[#1890FF] opacity-90 h-full"> |
||||
|
<div class="grid grid-cols-4 gap-1 h-full"> |
||||
|
<div class="col-span-3 mt-4 ml-4 text-white">项目总进度</div> |
||||
|
<div |
||||
|
class="col-span-1 flex justify-center items-center text-white text-4xl font-bold mr-20" |
||||
|
>{{planSummary.projectProgress }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="bg-[#1890FF] opacity-85 h-full"> |
||||
|
<div class="grid grid-cols-5 gap-1 h-full"> |
||||
|
<div class="col-span-2 mt-4 ml-4 text-white">总申报资金</div> |
||||
|
<div |
||||
|
class="col-span-2 flex justify-center items-center text-white text-4xl font-bold" |
||||
|
>{{ planSummary.totalMoney }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="bg-[#1890FF] opacity-80 h-full"> |
||||
|
<div class="grid grid-cols-5 gap-1 h-full"> |
||||
|
<div class="col-span-2 mt-4 ml-4 text-white">总中央资金</div> |
||||
|
<div |
||||
|
class="col-span-2 flex justify-center items-center text-white text-4xl font-bold " |
||||
|
>{{ planSummary.centralMoney }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</BasicTable> |
||||
|
</a-tab-pane> |
||||
|
<!-- <a-tab-pane key="2" tab="入库项目汇总(按层级)"> |
||||
|
<BasicTable @register="registerCengjiTable"> |
||||
|
<template #toolbar> |
||||
|
<div class="text-base font-bold">单位:(万元)</div> |
||||
|
<a-button type="primary" @click="showMore('cengji')" shape="round">更多</a-button> |
||||
|
</template> |
||||
|
<template #headerTop> |
||||
|
<div class="container mx-auto mt-4 mb-4 h-20"> |
||||
|
<div class="grid grid-cols-4 gap-4 h-full"> |
||||
|
<div class="bg-[#1890FF] opacity-100 h-full"> |
||||
|
<div class="grid grid-cols-4 gap-1 h-full"> |
||||
|
<div class="col-span-3 mt-4 ml-4 text-white">项目数量</div> |
||||
|
<div |
||||
|
class="col-span-1 flex justify-center items-center text-white text-4xl font-bold " |
||||
|
>{{ planSummary.projectNum }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="bg-[#1890FF] opacity-90 h-full"> |
||||
|
<div class="grid grid-cols-4 gap-1 h-full"> |
||||
|
<div class="col-span-3 mt-4 ml-4 text-white">项目总进度</div> |
||||
|
<div |
||||
|
class="col-span-1 flex justify-center items-center text-white text-4xl font-bold mr-20" |
||||
|
>{{planSummary.projectProgress }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="bg-[#1890FF] opacity-85 h-full"> |
||||
|
<div class="grid grid-cols-5 gap-1 h-full"> |
||||
|
<div class="col-span-2 mt-4 ml-4 text-white">总申报资金</div> |
||||
|
<div |
||||
|
class="col-span-2 flex justify-center items-center text-white text-4xl font-bold" |
||||
|
>{{ planSummary.totalMoney }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="bg-[#1890FF] opacity-80 h-full"> |
||||
|
<div class="grid grid-cols-5 gap-1 h-full"> |
||||
|
<div class="col-span-2 mt-4 ml-4 text-white">总中央资金</div> |
||||
|
<div |
||||
|
class="col-span-2 flex justify-center items-center text-white text-4xl font-bold " |
||||
|
>{{ planSummary.centralMoney }}</div |
||||
|
> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</BasicTable> |
||||
|
</a-tab-pane> --> |
||||
|
</a-tabs> |
||||
|
|
||||
|
<ShowMorePage @register="register" /> |
||||
|
</div> |
||||
|
</PageWrapper> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" name="planSummary" setup> |
||||
|
//ts语法 |
||||
|
import { ref, onMounted } from 'vue'; |
||||
|
import { BasicTable, useTable } from '@/components/Table'; |
||||
|
import { PageWrapper } from '@/components/Page'; |
||||
|
import { renwuColumn, cengjiColumn } from '@/views/projectSummary/planSummary/planSummary.data'; |
||||
|
import { |
||||
|
getProjectSummaryPage, |
||||
|
getProjectSummaryPageByTask, |
||||
|
} from '@/views/projectSummary/planSummary/planSummary.api'; |
||||
|
import { useModal, BasicModal } from '@/components/Modal'; |
||||
|
import ShowMorePage from './ShowMorePage.vue'; |
||||
|
const [register, { openModal }] = useModal(); |
||||
|
|
||||
|
onMounted(async () => {}); |
||||
|
let planSummary = ref<any>({ |
||||
|
projectNum: '', |
||||
|
centralMoney: '', |
||||
|
totalMoney: '', |
||||
|
projectProgress: '', |
||||
|
}); |
||||
|
let activeKey = ref('1'); |
||||
|
const [registerRenwuTable,{ reload:rwload }] = useTable({ |
||||
|
api: getProjectSummaryPageByTask, |
||||
|
title: '入库项目汇总', |
||||
|
columns: renwuColumn, |
||||
|
rowKey: 'projectName', |
||||
|
showIndexColumn: false, |
||||
|
useSearchForm: false, |
||||
|
showSummary: true, |
||||
|
summaryFunc: onSummary, |
||||
|
// actionColumn: { |
||||
|
// width: 140, |
||||
|
// title: '操作', |
||||
|
// dataIndex: 'action', |
||||
|
// slots: { customRender: 'action' }, |
||||
|
// }, |
||||
|
}); |
||||
|
const [registerCengjiTable,{ reload:cjload }] = useTable({ |
||||
|
api: getProjectSummaryPage, |
||||
|
title: '入库项目汇总', |
||||
|
columns: cengjiColumn, |
||||
|
rowKey: 'projectName', |
||||
|
showIndexColumn: false, |
||||
|
useSearchForm: false, |
||||
|
showSummary: true, |
||||
|
summaryFunc: onSummary, |
||||
|
// actionColumn: { |
||||
|
// width: 140, |
||||
|
// title: '操作', |
||||
|
// dataIndex: 'action', |
||||
|
// slots: { customRender: 'action' }, |
||||
|
// }, |
||||
|
}); |
||||
|
function mapTableTotalSummary(tableData, fields) { |
||||
|
let totals = {}; |
||||
|
fields.forEach((field) => { |
||||
|
totals[field] = tableData.reduce((acc, item) => acc + Number(item[field]), 0); |
||||
|
}); |
||||
|
return totals; |
||||
|
} |
||||
|
function showMore(type) { |
||||
|
openModal(true, { type: type }); |
||||
|
console.log(type); |
||||
|
} |
||||
|
function onSummary(tableData: Recordable[]) { |
||||
|
const totals = mapTableTotalSummary(tableData, [ |
||||
|
'projectNum', |
||||
|
'projectProgress', |
||||
|
'totalMoney', |
||||
|
'centralMoney', |
||||
|
]); |
||||
|
console.log('onSummary****totals>>>', totals); |
||||
|
planSummary.value = { |
||||
|
projectNum: totals.projectNum, |
||||
|
centralMoney: (totals.centralMoney/10000).toFixed(2), |
||||
|
totalMoney: (totals.totalMoney/10000).toFixed(2), |
||||
|
projectProgress: ((totals.projectProgress / tableData.length)*100).toFixed(2)+"%", |
||||
|
} |
||||
|
return [ |
||||
|
// // totals, |
||||
|
{ |
||||
|
reformName: '总计', |
||||
|
// superLeader:"总计", |
||||
|
dutyWorkplace: '总计', |
||||
|
// 计算平均值 |
||||
|
projectNum: totals.projectNum, |
||||
|
centralMoney: totals.centralMoney, |
||||
|
totalMoney: totals.totalMoney, |
||||
|
projectProgress: (totals.projectProgress / tableData.length).toFixed(2), |
||||
|
}, |
||||
|
]; |
||||
|
} |
||||
|
function handleTabChange(key) { |
||||
|
// activeKey.value = key; |
||||
|
if (key === '1') { |
||||
|
rwload(); |
||||
|
} else { |
||||
|
cjload(); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.timeline { |
||||
|
display: flex; |
||||
|
width: 100%; |
||||
|
margin-bottom: 100px; |
||||
|
|
||||
|
.lineitem { |
||||
|
transform: translateX(50%); |
||||
|
width: 25%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
::v-deep .el-timeline-item__tail { |
||||
|
border-left: none; |
||||
|
width: 100%; |
||||
|
border-top: 2px solid #e4e7ed; |
||||
|
position: absolute; |
||||
|
top: 6px; |
||||
|
} |
||||
|
|
||||
|
::v-deep .el-timeline-item__wrapper { |
||||
|
padding-left: 0; |
||||
|
position: absolute; |
||||
|
top: 20px; |
||||
|
transform: translateX(-50%); |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
::v-deep .el-timeline-item__timestamp { |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.nested-timeline { |
||||
|
margin-left: 20px; |
||||
|
border-left: 1px dashed #ccc; |
||||
|
padding-left: 20px; |
||||
|
} |
||||
|
|
||||
|
.nested-timeline-item { |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
::v-deep .ant-table-expanded-row { |
||||
|
height: auto !important; |
||||
|
/* 其他样式 */ |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue