npmapps 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/app/watchNginxConfig/node_modules/.package-lock.json +35 -0
- package/app/watchNginxConfig/node_modules/chokidar/LICENSE +21 -0
- package/app/watchNginxConfig/node_modules/chokidar/README.md +305 -0
- package/app/watchNginxConfig/node_modules/chokidar/esm/handler.d.ts +90 -0
- package/app/watchNginxConfig/node_modules/chokidar/esm/handler.js +629 -0
- package/app/watchNginxConfig/node_modules/chokidar/esm/index.d.ts +215 -0
- package/app/watchNginxConfig/node_modules/chokidar/esm/index.js +798 -0
- package/app/watchNginxConfig/node_modules/chokidar/esm/package.json +1 -0
- package/app/watchNginxConfig/node_modules/chokidar/handler.d.ts +90 -0
- package/app/watchNginxConfig/node_modules/chokidar/handler.js +635 -0
- package/app/watchNginxConfig/node_modules/chokidar/index.d.ts +215 -0
- package/app/watchNginxConfig/node_modules/chokidar/index.js +804 -0
- package/app/watchNginxConfig/node_modules/chokidar/package.json +69 -0
- package/app/watchNginxConfig/node_modules/readdirp/LICENSE +21 -0
- package/app/watchNginxConfig/node_modules/readdirp/README.md +120 -0
- package/app/watchNginxConfig/node_modules/readdirp/esm/index.d.ts +108 -0
- package/app/watchNginxConfig/node_modules/readdirp/esm/index.js +257 -0
- package/app/watchNginxConfig/node_modules/readdirp/esm/package.json +1 -0
- package/app/watchNginxConfig/node_modules/readdirp/index.d.ts +108 -0
- package/app/watchNginxConfig/node_modules/readdirp/index.js +263 -0
- package/app/watchNginxConfig/node_modules/readdirp/package.json +70 -0
- package/app/watchNginxConfig/package-lock.json +40 -0
- package/app/watchNginxConfig/package.json +5 -0
- package/app/watchNginxConfig/start_nginx_watcher.bat +4 -0
- package/app/watchNginxConfig/watchNginxConfig.js +104 -0
- package/package.json +1 -1
- package/app/components/attendanceCycle/index.vue +0 -131
- package/app/components/attendanceGroup/index.vue +0 -147
- package/app/components/attendancePersonnel/index.vue +0 -158
- package/app/components/companyCalendar/index.vue +0 -147
- package/app/components/shift/index.vue +0 -147
- package/app/components/shiftRotationSystem/index.vue +0 -147
- package/app/employeeSchedulingManagement/batchScheduling/index.vue +0 -401
- package/app/employeeSchedulingManagement/batchShiftChange/index.vue +0 -204
- package/app/employeeSchedulingManagement/data.js +0 -768
- package/app/employeeSchedulingManagement/index.vue +0 -436
- package/app/employeeSchedulingManagement/shiftChangeRecord/index.vue +0 -250
- package/app/employeeSchedulingManagement/shiftItem.vue +0 -107
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReaddirpStream = exports.EntryTypes = void 0;
|
|
4
|
+
exports.readdirp = readdirp;
|
|
5
|
+
exports.readdirpPromise = readdirpPromise;
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const node_stream_1 = require("node:stream");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
exports.EntryTypes = {
|
|
10
|
+
FILE_TYPE: 'files',
|
|
11
|
+
DIR_TYPE: 'directories',
|
|
12
|
+
FILE_DIR_TYPE: 'files_directories',
|
|
13
|
+
EVERYTHING_TYPE: 'all',
|
|
14
|
+
};
|
|
15
|
+
const defaultOptions = {
|
|
16
|
+
root: '.',
|
|
17
|
+
fileFilter: (_entryInfo) => true,
|
|
18
|
+
directoryFilter: (_entryInfo) => true,
|
|
19
|
+
type: exports.EntryTypes.FILE_TYPE,
|
|
20
|
+
lstat: false,
|
|
21
|
+
depth: 2147483648,
|
|
22
|
+
alwaysStat: false,
|
|
23
|
+
highWaterMark: 4096,
|
|
24
|
+
};
|
|
25
|
+
Object.freeze(defaultOptions);
|
|
26
|
+
const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';
|
|
27
|
+
const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);
|
|
28
|
+
const ALL_TYPES = [
|
|
29
|
+
exports.EntryTypes.DIR_TYPE,
|
|
30
|
+
exports.EntryTypes.EVERYTHING_TYPE,
|
|
31
|
+
exports.EntryTypes.FILE_DIR_TYPE,
|
|
32
|
+
exports.EntryTypes.FILE_TYPE,
|
|
33
|
+
];
|
|
34
|
+
const DIR_TYPES = new Set([
|
|
35
|
+
exports.EntryTypes.DIR_TYPE,
|
|
36
|
+
exports.EntryTypes.EVERYTHING_TYPE,
|
|
37
|
+
exports.EntryTypes.FILE_DIR_TYPE,
|
|
38
|
+
]);
|
|
39
|
+
const FILE_TYPES = new Set([
|
|
40
|
+
exports.EntryTypes.EVERYTHING_TYPE,
|
|
41
|
+
exports.EntryTypes.FILE_DIR_TYPE,
|
|
42
|
+
exports.EntryTypes.FILE_TYPE,
|
|
43
|
+
]);
|
|
44
|
+
const isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);
|
|
45
|
+
const wantBigintFsStats = process.platform === 'win32';
|
|
46
|
+
const emptyFn = (_entryInfo) => true;
|
|
47
|
+
const normalizeFilter = (filter) => {
|
|
48
|
+
if (filter === undefined)
|
|
49
|
+
return emptyFn;
|
|
50
|
+
if (typeof filter === 'function')
|
|
51
|
+
return filter;
|
|
52
|
+
if (typeof filter === 'string') {
|
|
53
|
+
const fl = filter.trim();
|
|
54
|
+
return (entry) => entry.basename === fl;
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(filter)) {
|
|
57
|
+
const trItems = filter.map((item) => item.trim());
|
|
58
|
+
return (entry) => trItems.some((f) => entry.basename === f);
|
|
59
|
+
}
|
|
60
|
+
return emptyFn;
|
|
61
|
+
};
|
|
62
|
+
/** Readable readdir stream, emitting new files as they're being listed. */
|
|
63
|
+
class ReaddirpStream extends node_stream_1.Readable {
|
|
64
|
+
constructor(options = {}) {
|
|
65
|
+
super({
|
|
66
|
+
objectMode: true,
|
|
67
|
+
autoDestroy: true,
|
|
68
|
+
highWaterMark: options.highWaterMark,
|
|
69
|
+
});
|
|
70
|
+
const opts = { ...defaultOptions, ...options };
|
|
71
|
+
const { root, type } = opts;
|
|
72
|
+
this._fileFilter = normalizeFilter(opts.fileFilter);
|
|
73
|
+
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
74
|
+
const statMethod = opts.lstat ? promises_1.lstat : promises_1.stat;
|
|
75
|
+
// Use bigint stats if it's windows and stat() supports options (node 10+).
|
|
76
|
+
if (wantBigintFsStats) {
|
|
77
|
+
this._stat = (path) => statMethod(path, { bigint: true });
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this._stat = statMethod;
|
|
81
|
+
}
|
|
82
|
+
this._maxDepth = opts.depth ?? defaultOptions.depth;
|
|
83
|
+
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
84
|
+
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
85
|
+
this._wantsEverything = type === exports.EntryTypes.EVERYTHING_TYPE;
|
|
86
|
+
this._root = (0, node_path_1.resolve)(root);
|
|
87
|
+
this._isDirent = !opts.alwaysStat;
|
|
88
|
+
this._statsProp = this._isDirent ? 'dirent' : 'stats';
|
|
89
|
+
this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
|
|
90
|
+
// Launch stream with one parent, the root dir.
|
|
91
|
+
this.parents = [this._exploreDir(root, 1)];
|
|
92
|
+
this.reading = false;
|
|
93
|
+
this.parent = undefined;
|
|
94
|
+
}
|
|
95
|
+
async _read(batch) {
|
|
96
|
+
if (this.reading)
|
|
97
|
+
return;
|
|
98
|
+
this.reading = true;
|
|
99
|
+
try {
|
|
100
|
+
while (!this.destroyed && batch > 0) {
|
|
101
|
+
const par = this.parent;
|
|
102
|
+
const fil = par && par.files;
|
|
103
|
+
if (fil && fil.length > 0) {
|
|
104
|
+
const { path, depth } = par;
|
|
105
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));
|
|
106
|
+
const awaited = await Promise.all(slice);
|
|
107
|
+
for (const entry of awaited) {
|
|
108
|
+
if (!entry)
|
|
109
|
+
continue;
|
|
110
|
+
if (this.destroyed)
|
|
111
|
+
return;
|
|
112
|
+
const entryType = await this._getEntryType(entry);
|
|
113
|
+
if (entryType === 'directory' && this._directoryFilter(entry)) {
|
|
114
|
+
if (depth <= this._maxDepth) {
|
|
115
|
+
this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
|
|
116
|
+
}
|
|
117
|
+
if (this._wantsDir) {
|
|
118
|
+
this.push(entry);
|
|
119
|
+
batch--;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if ((entryType === 'file' || this._includeAsFile(entry)) &&
|
|
123
|
+
this._fileFilter(entry)) {
|
|
124
|
+
if (this._wantsFile) {
|
|
125
|
+
this.push(entry);
|
|
126
|
+
batch--;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const parent = this.parents.pop();
|
|
133
|
+
if (!parent) {
|
|
134
|
+
this.push(null);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
this.parent = await parent;
|
|
138
|
+
if (this.destroyed)
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
this.destroy(error);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
this.reading = false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async _exploreDir(path, depth) {
|
|
151
|
+
let files;
|
|
152
|
+
try {
|
|
153
|
+
files = await (0, promises_1.readdir)(path, this._rdOptions);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
this._onError(error);
|
|
157
|
+
}
|
|
158
|
+
return { files, depth, path };
|
|
159
|
+
}
|
|
160
|
+
async _formatEntry(dirent, path) {
|
|
161
|
+
let entry;
|
|
162
|
+
const basename = this._isDirent ? dirent.name : dirent;
|
|
163
|
+
try {
|
|
164
|
+
const fullPath = (0, node_path_1.resolve)((0, node_path_1.join)(path, basename));
|
|
165
|
+
entry = { path: (0, node_path_1.relative)(this._root, fullPath), fullPath, basename };
|
|
166
|
+
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
this._onError(err);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
return entry;
|
|
173
|
+
}
|
|
174
|
+
_onError(err) {
|
|
175
|
+
if (isNormalFlowError(err) && !this.destroyed) {
|
|
176
|
+
this.emit('warn', err);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.destroy(err);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async _getEntryType(entry) {
|
|
183
|
+
// entry may be undefined, because a warning or an error were emitted
|
|
184
|
+
// and the statsProp is undefined
|
|
185
|
+
if (!entry && this._statsProp in entry) {
|
|
186
|
+
return '';
|
|
187
|
+
}
|
|
188
|
+
const stats = entry[this._statsProp];
|
|
189
|
+
if (stats.isFile())
|
|
190
|
+
return 'file';
|
|
191
|
+
if (stats.isDirectory())
|
|
192
|
+
return 'directory';
|
|
193
|
+
if (stats && stats.isSymbolicLink()) {
|
|
194
|
+
const full = entry.fullPath;
|
|
195
|
+
try {
|
|
196
|
+
const entryRealPath = await (0, promises_1.realpath)(full);
|
|
197
|
+
const entryRealPathStats = await (0, promises_1.lstat)(entryRealPath);
|
|
198
|
+
if (entryRealPathStats.isFile()) {
|
|
199
|
+
return 'file';
|
|
200
|
+
}
|
|
201
|
+
if (entryRealPathStats.isDirectory()) {
|
|
202
|
+
const len = entryRealPath.length;
|
|
203
|
+
if (full.startsWith(entryRealPath) && full.substr(len, 1) === node_path_1.sep) {
|
|
204
|
+
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
|
|
205
|
+
// @ts-ignore
|
|
206
|
+
recursiveError.code = RECURSIVE_ERROR_CODE;
|
|
207
|
+
return this._onError(recursiveError);
|
|
208
|
+
}
|
|
209
|
+
return 'directory';
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
this._onError(error);
|
|
214
|
+
return '';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
_includeAsFile(entry) {
|
|
219
|
+
const stats = entry && entry[this._statsProp];
|
|
220
|
+
return stats && this._wantsEverything && !stats.isDirectory();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
exports.ReaddirpStream = ReaddirpStream;
|
|
224
|
+
/**
|
|
225
|
+
* Streaming version: Reads all files and directories in given root recursively.
|
|
226
|
+
* Consumes ~constant small amount of RAM.
|
|
227
|
+
* @param root Root directory
|
|
228
|
+
* @param options Options to specify root (start directory), filters and recursion depth
|
|
229
|
+
*/
|
|
230
|
+
function readdirp(root, options = {}) {
|
|
231
|
+
// @ts-ignore
|
|
232
|
+
let type = options.entryType || options.type;
|
|
233
|
+
if (type === 'both')
|
|
234
|
+
type = exports.EntryTypes.FILE_DIR_TYPE; // backwards-compatibility
|
|
235
|
+
if (type)
|
|
236
|
+
options.type = type;
|
|
237
|
+
if (!root) {
|
|
238
|
+
throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
|
|
239
|
+
}
|
|
240
|
+
else if (typeof root !== 'string') {
|
|
241
|
+
throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
|
|
242
|
+
}
|
|
243
|
+
else if (type && !ALL_TYPES.includes(type)) {
|
|
244
|
+
throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
|
|
245
|
+
}
|
|
246
|
+
options.root = root;
|
|
247
|
+
return new ReaddirpStream(options);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Promise version: Reads all files and directories in given root recursively.
|
|
251
|
+
* Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.
|
|
252
|
+
* @returns array of paths and their entry infos
|
|
253
|
+
*/
|
|
254
|
+
function readdirpPromise(root, options = {}) {
|
|
255
|
+
return new Promise((resolve, reject) => {
|
|
256
|
+
const files = [];
|
|
257
|
+
readdirp(root, options)
|
|
258
|
+
.on('data', (entry) => files.push(entry))
|
|
259
|
+
.on('end', () => resolve(files))
|
|
260
|
+
.on('error', (error) => reject(error));
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
exports.default = readdirp;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "readdirp",
|
|
3
|
+
"description": "Recursive version of fs.readdir with small RAM & CPU footprint.",
|
|
4
|
+
"version": "4.1.2",
|
|
5
|
+
"homepage": "https://github.com/paulmillr/readdirp",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git://github.com/paulmillr/readdirp.git"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/paulmillr/readdirp/issues"
|
|
13
|
+
},
|
|
14
|
+
"author": "Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
|
|
15
|
+
"contributors": [
|
|
16
|
+
"Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
|
|
17
|
+
"Paul Miller (https://paulmillr.com)"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">= 14.18.0"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"index.d.ts",
|
|
25
|
+
"index.d.ts.map",
|
|
26
|
+
"index.js.map",
|
|
27
|
+
"esm"
|
|
28
|
+
],
|
|
29
|
+
"main": "./index.js",
|
|
30
|
+
"module": "./esm/index.js",
|
|
31
|
+
"types": "./index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"import": "./esm/index.js",
|
|
35
|
+
"require": "./index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"keywords": [
|
|
40
|
+
"recursive",
|
|
41
|
+
"fs",
|
|
42
|
+
"stream",
|
|
43
|
+
"streams",
|
|
44
|
+
"readdir",
|
|
45
|
+
"filesystem",
|
|
46
|
+
"find",
|
|
47
|
+
"filter"
|
|
48
|
+
],
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc && tsc -p tsconfig.cjs.json",
|
|
51
|
+
"lint": "prettier --check index.ts test/index.test.js",
|
|
52
|
+
"format": "prettier --write index.ts test/index.test.js",
|
|
53
|
+
"test": "node test/index.test.js",
|
|
54
|
+
"test:coverage": "c8 node test/index.test.js"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@paulmillr/jsbt": "0.3.1",
|
|
58
|
+
"@types/node": "20.14.8",
|
|
59
|
+
"c8": "10.1.3",
|
|
60
|
+
"chai": "4.3.4",
|
|
61
|
+
"chai-subset": "1.6.0",
|
|
62
|
+
"micro-should": "0.5.0",
|
|
63
|
+
"prettier": "3.1.1",
|
|
64
|
+
"typescript": "5.5.2"
|
|
65
|
+
},
|
|
66
|
+
"funding": {
|
|
67
|
+
"type": "individual",
|
|
68
|
+
"url": "https://paulmillr.com/funding/"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node",
|
|
3
|
+
"lockfileVersion": 3,
|
|
4
|
+
"requires": true,
|
|
5
|
+
"packages": {
|
|
6
|
+
"": {
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"chokidar": "^4.0.3"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"node_modules/chokidar": {
|
|
12
|
+
"version": "4.0.3",
|
|
13
|
+
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
|
14
|
+
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"readdirp": "^4.0.1"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">= 14.16.0"
|
|
21
|
+
},
|
|
22
|
+
"funding": {
|
|
23
|
+
"url": "https://paulmillr.com/funding/"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"node_modules/readdirp": {
|
|
27
|
+
"version": "4.1.2",
|
|
28
|
+
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
|
29
|
+
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">= 14.18.0"
|
|
33
|
+
},
|
|
34
|
+
"funding": {
|
|
35
|
+
"type": "individual",
|
|
36
|
+
"url": "https://paulmillr.com/funding/"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const chokidar = require('chokidar');
|
|
2
|
+
const { exec } = require('child_process');
|
|
3
|
+
|
|
4
|
+
// Nginx配置文件目录,根据实际情况修改
|
|
5
|
+
const NGINX_CONFIG_DIR = 'C:/nginx/conf';
|
|
6
|
+
// Nginx可执行文件路径,根据实际情况修改
|
|
7
|
+
const NGINX_EXEC_PATH = 'C:/nginx/nginx.exe';
|
|
8
|
+
|
|
9
|
+
// 检查Nginx是否正在运行
|
|
10
|
+
function checkNginxStatus() {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
exec('tasklist /FI "IMAGENAME eq nginx.exe"', (error, stdout) => {
|
|
13
|
+
if (error) reject(error);
|
|
14
|
+
resolve(stdout.includes('nginx.exe'));
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 启动Nginx
|
|
20
|
+
function startNginx() {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
console.log('正在启动Nginx...');
|
|
23
|
+
exec(`"${NGINX_EXEC_PATH}"`, (error, stdout, stderr) => {
|
|
24
|
+
if (error) {
|
|
25
|
+
reject(`启动失败: ${error.message}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (stderr) {
|
|
29
|
+
reject(`Nginx错误: ${stderr}`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log('Nginx启动成功');
|
|
33
|
+
resolve();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 创建文件监听器
|
|
39
|
+
function startWatcher() {
|
|
40
|
+
const watcher = chokidar.watch(NGINX_CONFIG_DIR, {
|
|
41
|
+
ignored: /(^|\/\.)\../, // 忽略点文件
|
|
42
|
+
persistent: true,
|
|
43
|
+
ignoreInitial: true
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(`正在监听Nginx配置文件变化: ${NGINX_CONFIG_DIR}`);
|
|
47
|
+
|
|
48
|
+
watcher
|
|
49
|
+
.on('all', (event, path) => {
|
|
50
|
+
console.log(`检测到配置文件变化: ${path} (事件: ${event})`);
|
|
51
|
+
reloadNginxConfig();
|
|
52
|
+
})
|
|
53
|
+
.on('error', error => console.error('监听错误:', error));
|
|
54
|
+
|
|
55
|
+
return watcher;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 初始化流程
|
|
59
|
+
async function init() {
|
|
60
|
+
try {
|
|
61
|
+
const isRunning = await checkNginxStatus();
|
|
62
|
+
if (!isRunning) {
|
|
63
|
+
await startNginx();
|
|
64
|
+
} else {
|
|
65
|
+
console.log('Nginx已运行');
|
|
66
|
+
}
|
|
67
|
+
const watcher = startWatcher();
|
|
68
|
+
|
|
69
|
+
// 处理程序退出
|
|
70
|
+
process.on('SIGINT', () => {
|
|
71
|
+
console.log('正在关闭监听器...');
|
|
72
|
+
watcher.close().then(() => process.exit(0));
|
|
73
|
+
});
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('初始化失败:', error);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 启动应用
|
|
81
|
+
init();
|
|
82
|
+
|
|
83
|
+
// 重新加载Nginx配置
|
|
84
|
+
function reloadNginxConfig() {
|
|
85
|
+
console.log('正在重新加载Nginx配置...');
|
|
86
|
+
exec(`"${NGINX_EXEC_PATH}" -s reload`, (error, stdout, stderr) => {
|
|
87
|
+
if (error) {
|
|
88
|
+
console.error(`重新加载失败: ${error.message}`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (stderr) {
|
|
92
|
+
console.error(`Nginx错误输出: ${stderr}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
console.log('Nginx配置重新加载成功!');
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 处理程序退出
|
|
100
|
+
process.on('SIGINT', async () => {
|
|
101
|
+
console.log('正在关闭监听器...');
|
|
102
|
+
await watcher.close();
|
|
103
|
+
process.exit(0);
|
|
104
|
+
});
|
package/package.json
CHANGED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="attendanceCycle" v-loading="loading">
|
|
3
|
-
<div class="header">
|
|
4
|
-
<div class="left">
|
|
5
|
-
<el-button size="mini" type="primary" @click="onSave">选择</el-button>
|
|
6
|
-
</div>
|
|
7
|
-
<div class="right">
|
|
8
|
-
<el-select
|
|
9
|
-
size="mini"
|
|
10
|
-
v-model="year"
|
|
11
|
-
placeholder="请选择"
|
|
12
|
-
@change="yearChange"
|
|
13
|
-
>
|
|
14
|
-
<el-option
|
|
15
|
-
v-for="item in options"
|
|
16
|
-
:key="item.yearId"
|
|
17
|
-
:label="item.yearName"
|
|
18
|
-
:value="item.yearId"
|
|
19
|
-
>
|
|
20
|
-
</el-option>
|
|
21
|
-
</el-select>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
<el-table
|
|
25
|
-
size="mini"
|
|
26
|
-
:data="tableData"
|
|
27
|
-
style="width: 100%"
|
|
28
|
-
border
|
|
29
|
-
@row-click="handleRowClick"
|
|
30
|
-
>
|
|
31
|
-
<!-- 单选框列 -->
|
|
32
|
-
<el-table-column width="50">
|
|
33
|
-
<template slot-scope="scope">
|
|
34
|
-
<el-radio
|
|
35
|
-
:value="currentRow.monthId"
|
|
36
|
-
:label="scope.row.monthId"
|
|
37
|
-
> </el-radio>
|
|
38
|
-
</template>
|
|
39
|
-
</el-table-column>
|
|
40
|
-
<el-table-column prop="monthName" label="名称"></el-table-column>
|
|
41
|
-
<el-table-column prop="monthName" label="开始日期"></el-table-column>
|
|
42
|
-
<el-table-column prop="monthName" label="结束日期"></el-table-column>
|
|
43
|
-
</el-table>
|
|
44
|
-
</div>
|
|
45
|
-
</template>
|
|
46
|
-
|
|
47
|
-
<script>
|
|
48
|
-
import {
|
|
49
|
-
getOpenAttendanceCycleMonthListApi,
|
|
50
|
-
getOpenAttendanceCycleYearListApi,
|
|
51
|
-
} from "../../employeeSchedulingManagement/data.js";
|
|
52
|
-
|
|
53
|
-
export default {
|
|
54
|
-
// 考勤周期
|
|
55
|
-
props: {
|
|
56
|
-
close: {
|
|
57
|
-
type: Function,
|
|
58
|
-
default: () => {},
|
|
59
|
-
},
|
|
60
|
-
setData:{
|
|
61
|
-
type: Function,
|
|
62
|
-
default: () => {},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
data() {
|
|
67
|
-
return {
|
|
68
|
-
loading: false,
|
|
69
|
-
tableData: [],
|
|
70
|
-
year: "2025",
|
|
71
|
-
options: [],
|
|
72
|
-
currentRow: {
|
|
73
|
-
monthId: "",
|
|
74
|
-
}, // 当前选中的行
|
|
75
|
-
};
|
|
76
|
-
},
|
|
77
|
-
mounted() {
|
|
78
|
-
this.loading = false;
|
|
79
|
-
this.getTableData();
|
|
80
|
-
this.getYearList();
|
|
81
|
-
},
|
|
82
|
-
methods: {
|
|
83
|
-
getTableData() {
|
|
84
|
-
this.loading = true;
|
|
85
|
-
getOpenAttendanceCycleMonthListApi(this.year).then((res) => {
|
|
86
|
-
this.tableData = res;
|
|
87
|
-
console.log(res, "res");
|
|
88
|
-
this.loading = false;
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
getYearList() {
|
|
92
|
-
getOpenAttendanceCycleYearListApi().then((res) => {
|
|
93
|
-
this.options = res;
|
|
94
|
-
});
|
|
95
|
-
},
|
|
96
|
-
yearChange() {
|
|
97
|
-
this.getTableData();
|
|
98
|
-
},
|
|
99
|
-
handleRowClick(row) {
|
|
100
|
-
this.currentRow = row; // 点击行时更新选中状态
|
|
101
|
-
},
|
|
102
|
-
onSave() {
|
|
103
|
-
if (this.currentRow.monthId === "") {
|
|
104
|
-
return this.$message.error("请选择");
|
|
105
|
-
}
|
|
106
|
-
this.close();
|
|
107
|
-
this.setData(this.currentRow);
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
</script>
|
|
113
|
-
|
|
114
|
-
<style lang="less" scoped>
|
|
115
|
-
.attendanceCycle {
|
|
116
|
-
.header {
|
|
117
|
-
display: flex;
|
|
118
|
-
justify-content: space-between;
|
|
119
|
-
align-items: center;
|
|
120
|
-
margin-bottom: 10px;
|
|
121
|
-
.left {
|
|
122
|
-
display: flex;
|
|
123
|
-
align-items: center;
|
|
124
|
-
}
|
|
125
|
-
.right {
|
|
126
|
-
display: flex;
|
|
127
|
-
align-items: center;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
</style>
|