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> |
|||
<BasicModal 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'"/> |
|||
<projectPlanApproval :record="record" @close="exit" v-if="record.stage=='createPlaninfo'"/> |
|||
<planFileApproval :record="record" @close="exit" v-if="planfileNames.includes(record.stage)"/> |
|||
<fieldChangeApproval :record="record" @close="exit" v-if="record.stage=='fieldChange'"/> |
|||
<contractApproval :record="record" @close="exit" v-if="record.stage=='createContract'"/> |
|||
<uploadURTfileApproval :record="record" @close="exit" v-if="record.stage=='createURT'||record.stage=='createURT2'"/> |
|||
<MergeProjectApprova :record="record" @close="exit" v-if="record.stage=='MergeProject'"/> |
|||
<SplitProjectApprova :record="record" @close="exit" v-if="record.stage=='SplitProject'"/> |
|||
</BasicModal> |
|||
<BasicModal |
|||
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'" /> |
|||
<projectPlanApproval :record="record" @close="exit" v-if="record.stage == 'createPlaninfo'" /> |
|||
<planFileApproval :record="record" @close="exit" v-if="planfileNames.includes(record.stage)" /> |
|||
<fieldChangeApproval :record="record" @close="exit" v-if="record.stage == 'fieldChange'" /> |
|||
<contractApproval :record="record" @close="exit" v-if="record.stage == 'createContract'" /> |
|||
<uploadURTfileApproval |
|||
:record="record" |
|||
@close="exit" |
|||
v-if="record.stage == 'createURT' || record.stage == 'createURT2'" |
|||
/> |
|||
<MergeProjectApprova :record="record" @close="exit" v-if="record.stage == 'MergeProject'" /> |
|||
<SplitProjectApprova :record="record" @close="exit" v-if="record.stage == 'SplitProject'" /> |
|||
</BasicModal> |
|||
</template> |
|||
<script lang="ts" name="ApprovalPageModel" setup> |
|||
import {ref} from "vue" |
|||
import { BasicModal, useModalInner } from '@/components/Modal'; |
|||
import { ref } from 'vue'; |
|||
import { BasicModal, useModalInner } from '@/components/Modal'; |
|||
|
|||
import initiatesProjectsApproval from "../initiatesProjectsApproval.vue" |
|||
import planFileApproval from '@/views/ProcessApprovalSubPage/planFileApproval.vue' |
|||
import uploadfileApproval from '../uploadfileApproval.vue' |
|||
import projectPlanApproval from '../projectPlanApproval.vue' |
|||
import fieldChangeApproval from '../fieldChangeApproval.vue' |
|||
import contractApproval from '../contractApproval.vue' |
|||
import uploadURTfileApproval from '../uploadURTfileApproval.vue' |
|||
import MergeProjectApprova from '../MergeProjectApprova.vue' |
|||
import SplitProjectApprova from '../SplitProjectApprova.vue' |
|||
import initiatesProjectsApproval from '../initiatesProjectsApproval.vue'; |
|||
import planFileApproval from '@/views/ProcessApprovalSubPage/planFileApproval.vue'; |
|||
import uploadfileApproval from '../uploadfileApproval.vue'; |
|||
import projectPlanApproval from '../projectPlanApproval.vue'; |
|||
import fieldChangeApproval from '../fieldChangeApproval.vue'; |
|||
import contractApproval from '../contractApproval.vue'; |
|||
import uploadURTfileApproval from '../uploadURTfileApproval.vue'; |
|||
import MergeProjectApprova from '../MergeProjectApprova.vue'; |
|||
import SplitProjectApprova from '../SplitProjectApprova.vue'; |
|||
|
|||
const planfileNames = ["projectApprovalStage","feasibilityTechReviewConfirm","finalFeasibilityReportDraft","centralizedCheck","createPlaninfoFile","bidDocumentsPreparation","costEvalReportConfirm"] |
|||
const [registerModal, { closeModal }] = useModalInner(init); |
|||
defineProps(["record"]) |
|||
|
|||
let processName= ref() |
|||
let emit = defineEmits(["close"]) |
|||
function exit(){ |
|||
closeModal() |
|||
console.log("ApprovalPageModel") |
|||
emit("close") |
|||
} |
|||
function init(initData){ |
|||
processName.value=initData.record.processName |
|||
} |
|||
const planfileNames = [ |
|||
'projectApprovalStage', |
|||
'feasibilityTechReviewConfirm', |
|||
'finalFeasibilityReportDraft', |
|||
'centralizedCheck', |
|||
'createPlaninfoFile', |
|||
'bidDocumentsPreparation', |
|||
'costEvalReportConfirm', |
|||
"chuBuSheJiShenPi", |
|||
"zhongYanJieDuan", |
|||
"chuYanJieDuan", |
|||
"shouFuZhiFu", |
|||
"heTongQianDing" |
|||
]; |
|||
const [registerModal, { closeModal }] = useModalInner(init); |
|||
defineProps(['record']); |
|||
|
|||
let processName = ref(); |
|||
let emit = defineEmits(['close']); |
|||
function exit() { |
|||
closeModal(); |
|||
console.log('ApprovalPageModel'); |
|||
emit('close'); |
|||
} |
|||
function init(initData) { |
|||
processName.value = initData.record.processName; |
|||
} |
|||
</script> |
|||
<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