87 changed files with 7234 additions and 52177 deletions
File diff suppressed because it is too large
Binary file not shown.
@ -0,0 +1,21 @@ |
|||
<?php |
|||
|
|||
require_once('../conn.php'); |
|||
|
|||
$person = $_GET['person']; |
|||
$floor = $_GET['floor']; |
|||
|
|||
$sql_str = "SELECT id, price FROM demolition_price WHERE seat = :person AND floor = :floor AND status = 'Y' ORDER BY id DESC LIMIT 1"; |
|||
|
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':person', $person); |
|||
$stmt->bindParam(':floor', $floor); |
|||
$stmt->execute(); |
|||
|
|||
$demolish = $stmt->fetch(PDO::FETCH_ASSOC); |
|||
|
|||
if($demolish){ |
|||
echo json_encode(['price'=> $demolish['price'], 'id'=> $demolish['id']]); |
|||
}else{ |
|||
echo false; |
|||
} |
@ -0,0 +1,58 @@ |
|||
<?php |
|||
require_once("../conn.php"); |
|||
function createFlow($mid, $current_assigner, $flow_code, $ekind, $form_key=null){ |
|||
global $conn; |
|||
$form_id = $mid; |
|||
$seq = 0; |
|||
$system_id = "prm"; |
|||
if($ekind == "新梯") $flow_id = "prm01"; |
|||
if($ekind == "汰改") $flow_id = "prm02"; |
|||
if($ekind == "保養") $flow_id = "prm03"; |
|||
|
|||
if($form_key == null){ |
|||
$sql_str = "SELECT appwms.nextval('form_key') form_key"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->execute(); |
|||
$result = $stmt->fetch(PDO::FETCH_ASSOC); |
|||
$form_key = $result['form_key']; |
|||
$seq = 0; |
|||
|
|||
$sql_str = "INSERT INTO flow (system_id, flow_id, form_id, form_key, flow_code) |
|||
VALUES (:system_id, :flow_id, :form_id, :form_key, :flow_code)"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':system_id', $system_id); |
|||
$stmt->bindParam(':flow_id', $flow_id); |
|||
$stmt->bindParam(':form_id', $form_id); |
|||
$stmt->bindParam(':form_key', $form_key); |
|||
$stmt->bindParam(':flow_code', $flow_code); |
|||
$stmt->execute(); |
|||
}else{ |
|||
$sql_str = "UPDATE flow SET flow_code = :flow_code WHERE form_key = :form_key"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':form_key', $form_key); |
|||
$stmt->bindParam(':flow_code', $flow_code); |
|||
$stmt->execute(); |
|||
|
|||
$sql_str = "SELECT MAX(seq) AS max_seq FROM subflow WHERE form_key = :form_key"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':form_key', $form_key); |
|||
$stmt->execute(); |
|||
$result = $stmt->fetch(PDO::FETCH_ASSOC); |
|||
$seq = $result['max_seq']; |
|||
$seq ++; |
|||
} |
|||
|
|||
$created_at = date("Y-m-d H:i:s"); |
|||
$sql_str = "INSERT INTO subflow (form_key, seq, current_assigner, update_date,create_date) |
|||
VALUES (:form_key, :seq, :current_assigner, :update_date,:create_date)"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':form_key', $form_key); |
|||
$stmt->bindParam(':seq', $seq); |
|||
$stmt->bindParam(':current_assigner', $current_assigner); |
|||
$stmt->bindParam(':update_date', $created_at); |
|||
$stmt->bindParam(':create_date', $created_at); |
|||
$stmt->execute(); |
|||
|
|||
|
|||
return $form_key; |
|||
} |
@ -0,0 +1,20 @@ |
|||
<?php |
|||
require_once("../conn.php"); |
|||
function sendSystemNotice($kind, $related_id, $title, $content, $haveread, $permissions, $creater, $create_at, $url){ |
|||
global $conn; |
|||
$sql_str = "INSERT INTO notice (kind, related_id, title, content, haveread, permission, url, creater, create_at) |
|||
VALUES (:kind, :related_id, :title, :content, :haveread, :permission, :url,:creater, :create_at)"; |
|||
foreach($permissions as $permission){ |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':kind', $kind); |
|||
$stmt->bindParam(':related_id', $related_id); |
|||
$stmt->bindParam(':title', $title); |
|||
$stmt->bindParam(':content', $content); |
|||
$stmt->bindParam(':haveread', $haveread); |
|||
$stmt->bindParam(':permission', $permission); |
|||
$stmt->bindParam(':url', $url); |
|||
$stmt->bindParam(':creater', $creater); |
|||
$stmt->bindParam(':create_at', $create_at); |
|||
$stmt->execute(); |
|||
} |
|||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,56 @@ |
|||
<?php |
|||
|
|||
require_once("../conn.php"); |
|||
date_default_timezone_set('Asia/Taipei'); |
|||
|
|||
$contractno = $_POST['contractno']; |
|||
$ekind = $_POST['ekind']; |
|||
$person = $_POST['person']; |
|||
$company = $_POST['company']; |
|||
$case_name = $_POST['case_name']; |
|||
$address = $_POST['address']; |
|||
$compete = ""; |
|||
$price_lowest = $_POST['price_lowest']; |
|||
$price_total = $_POST['price_total']; |
|||
$price_rate = $_POST['price_rate']; |
|||
$special_fee = $_POST['special_fee']; |
|||
$predeal_date = $_POST['predeal_date']; |
|||
$penalty = $_POST['penalty']; |
|||
$deposit_rate = $_POST['deposit_rate']; |
|||
$warranty_rate = $_POST['warranty_rate']; |
|||
$keep_rate = $_POST['keep_rate']; |
|||
$memo = $_POST['memo']; |
|||
$status = $_POST['status']; |
|||
$attatch1 = $_POST['attatch1'] =='' ? NULL : $_POST['attatch1']; |
|||
$attatch2 = $_POST['attatch2'] =='' ? NULL : $_POST['attatch2']; |
|||
$creater = "M0174"; |
|||
$create_at = date("Y-m-d H:i:s"); |
|||
|
|||
|
|||
$elevators = $_POST['elevators']; |
|||
$options = $_POST['options']; |
|||
$otherOptions = $_POST['otherOptions']; |
|||
$maintainOptions = $_POST['maintainOptions']; |
|||
|
|||
$paymentRatio = $_POST['paymentRatio']; |
|||
|
|||
$sql_str = "SELECT id FROM pricereview_main WHERE contractno = :contractno ORDER BY id DESC LIMIT 1"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':contractno', $contractno); |
|||
$stmt->execute(); |
|||
$main = $stmt->fetch(PDO::FETCH_ASSOC); |
|||
|
|||
if(!$main){ |
|||
insertPricereview(); |
|||
}else{ |
|||
updatePricereview(); |
|||
} |
|||
|
|||
$mid = $main['id']; |
|||
|
|||
function insertPricereview(){ |
|||
|
|||
} |
|||
function updatePricereview(){ |
|||
|
|||
} |
@ -0,0 +1,101 @@ |
|||
<?php |
|||
|
|||
if(isset($_GET['id']) && $_GET['id'] == 998){ |
|||
require_once('../conn.php'); |
|||
include_once('./postFlow.php'); |
|||
|
|||
$sql_str = "SELECT pricereview_sign.*, pricereview_main.ekind AS ekind FROM pricereview_sign LEFT JOIN pricereview_main ON pricereview_sign.mid = pricereview_main.id WHERE pricereview_main.status = 'YS' "; |
|||
$sql_str = "SELECT |
|||
prs.*, |
|||
prm.ekind |
|||
FROM |
|||
(SELECT |
|||
MAX(id) AS max_id, |
|||
mid |
|||
FROM |
|||
pricereview_sign |
|||
GROUP BY |
|||
mid) AS max_prs |
|||
JOIN |
|||
pricereview_sign prs ON prs.id = max_prs.max_id |
|||
LEFT JOIN |
|||
pricereview_main prm ON prs.mid = prm.id |
|||
WHERE |
|||
prm.status = 'YS'"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->execute(); |
|||
$signs = $stmt->fetchAll(PDO::FETCH_ASSOC); |
|||
$total = 0; |
|||
foreach($signs as $sign){ |
|||
$total++; |
|||
echo $total . "<br>"; |
|||
$currentSigner = ""; |
|||
$form_key = null; |
|||
if(!empty($sign['sign1'])){ |
|||
$sign1 = explode(",", $sign['sign1'])[1]; // M0033,, |
|||
if($sign1 == ""){ |
|||
$currentSigner = explode(",", $sign['sign1'])[0]; |
|||
$form_key = createFlow($sign['mid'], $currentSigner, "A", $sign['ekind'], $form_key ); |
|||
continue; |
|||
}else{ |
|||
if(!empty($sign['sign2'])){ |
|||
$sign2 = explode(",", $sign['sign2'])[1]; |
|||
if($sign2 == "" && $sign1 == "Y"){ |
|||
$currentSigner = explode(",", $sign['sign1'])[0]; |
|||
$form_key = createFlow($sign['mid'], $currentSigner, "A", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign2'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
continue; |
|||
} |
|||
$sign3 = explode(",", $sign['sign3'])[1]; |
|||
if($sign3 == "" && $sign2 == "Y"){ |
|||
$currentSigner = explode(",", $sign['sign1'])[0]; |
|||
$form_key = createFlow($sign['mid'], $currentSigner, "A", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign2'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign3'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
continue; |
|||
} |
|||
if(!empty($sign['sign4'])){ |
|||
$sign4 = explode(",", $sign['sign4'])[1]; |
|||
if($sign4 == "" && $sign3 == "Y"){ |
|||
$currentSigner = explode(",", $sign['sign1'])[0]; |
|||
$form_key = createFlow($sign['mid'], $currentSigner, "A", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign2'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign3'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign4'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
}else{ |
|||
$sign3 = explode(",", $sign['sign3'])[1]; |
|||
if($sign3 == "" && $sign1 == "Y"){ |
|||
$currentSigner = explode(",", $sign['sign1'])[0]; |
|||
$form_key = createFlow($sign['mid'], $currentSigner, "A", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign3'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
continue; |
|||
} |
|||
if(!empty($sign['sign4'])){ |
|||
$sign4 = explode(",", $sign['sign4'])[1]; |
|||
if($sign4 == "" && $sign3 == "Y"){ |
|||
$currentSigner = explode(",", $sign['sign1'])[0]; |
|||
$form_key = createFlow($sign['mid'], $currentSigner, "A", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign3'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
$currentSigner = explode(",", $sign['sign4'])[0]; |
|||
createFlow($sign['mid'], $currentSigner, "B", $sign['ekind'], $form_key ); |
|||
continue; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,51 @@ |
|||
<?php |
|||
|
|||
require_once "../conn.php"; |
|||
|
|||
if(!isset($_GET['id'])) exit; |
|||
$id = $_GET['id']; |
|||
if($id!=969) exit; |
|||
|
|||
$sql_str = "SELECT * FROM pricereview_sign"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->execute(); |
|||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); |
|||
|
|||
foreach($result as $sign){ |
|||
$endSign = false; |
|||
if(explode(",", $sign['sign3'])[1] == "Y"){ |
|||
$newSign3 = str_replace("Y", "YY", $sign['sign3']); |
|||
$sign4_is_null = $sign['sign4'] == null ? true : false; |
|||
$sql_str = $sign4_is_null ? "UPDATE pricereview_sign SET sign3 = :sign3 WHERE id = :id" : "UPDATE pricereview_sign SET sign3 = :sign3, sign4 = NULL, sign_total = sign_total - 1 WHERE id = :id"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':sign3', $newSign3); |
|||
$stmt->bindParam(':id', $sign['id']); |
|||
$stmt->execute(); |
|||
|
|||
$sql_str = "UPDATE pricereview_main SET status = 'YY' WHERE id = :id AND status = 'YS' "; |
|||
|
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':id', $sign['mid']); |
|||
$stmt->execute(); |
|||
|
|||
$sql_str = "UPDATE flow SET flow_code = 'Z' WHERE form_id = :id AND system_id = 'prm' AND (flow_id = 'prm01' OR flow_id = 'prm02')"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':id', $sign['mid']); |
|||
$stmt->execute(); |
|||
|
|||
echo $sign['mid']; |
|||
echo "<br>"; |
|||
}else{ |
|||
if($sign['sign4'] != NULL){ |
|||
$sql_str = "UPDATE pricereview_sign SET sign4 = NULL, sign_total = sign_total + 1 WHERE id = :id AND sign4 IS NOT NULL"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
$stmt->bindParam(':id', $sign['id']); |
|||
$stmt->execute(); |
|||
|
|||
echo $sign['mid']; |
|||
echo "<br>"; |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
File diff suppressed because it is too large
@ -1,10 +1 @@ |
|||
{ |
|||
"version": 3, |
|||
"sources": [ |
|||
"pricereview.scss", |
|||
"pricereview.css" |
|||
], |
|||
"names": [], |
|||
"mappings": "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", |
|||
"file": "pricereview.css" |
|||
} |
|||
{"version":3,"sources":["pricereview.css","pricereview.scss"],"names":[],"mappings":"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","file":"pricereview.css"} |
@ -0,0 +1,76 @@ |
|||
<?php |
|||
|
|||
require_once "./conn.php"; |
|||
|
|||
$sql_str = "SELECT pricereview_main.*, account.name AS person_name FROM pricereview_main |
|||
LEFT JOIN account ON account.accountid = pricereview_main.person |
|||
WHERE pricereview_main.status <> 'D' |
|||
AND pricereview_main.create_at >= '2024-01-01' |
|||
AND pricereview_main.create_at <= '2024-01-31' |
|||
AND ekind = '汰改'"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
// $stmt->bindParam(':vol_no', $vol_no); |
|||
$stmt->execute(); |
|||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); |
|||
|
|||
|
|||
|
|||
|
|||
?> |
|||
|
|||
|
|||
<table border=1> |
|||
<tr> |
|||
<th>ID</th> |
|||
<th>卷號</th> |
|||
<th>營業員</th> |
|||
<th>客戶名稱</th> |
|||
<th>案件名稱</th> |
|||
<th>牌價總額</th> |
|||
<th>售價總額</th> |
|||
<th>價率</th> |
|||
<th>預定成交日</th> |
|||
<th>預定交期</th> |
|||
<th>建檔人</th> |
|||
<th>建檔時間</th> |
|||
<th>狀態</th> |
|||
</tr> |
|||
<?php foreach($result as $item): ?> |
|||
<tr> |
|||
<td><?php echo $item['id']; ?></td> |
|||
<td><?php echo $item['contractno']; ?></td> |
|||
<td><?php echo $item['person_name']; ?></td> |
|||
<td><?php echo $item['company']; ?></td> |
|||
<td><?php echo $item['case_name']; ?></td> |
|||
<td><?php echo $item['price_lowest']; ?></td> |
|||
<td><?php echo $item['price_total']; ?></td> |
|||
<td><?php echo ((int)$item['price_total'] / (int)$item['price_lowest'] * 100) ."%"; ?></td> |
|||
<td><?php echo $item['predeal_date']; ?></td> |
|||
<td><?php echo $item['facilitok_date']; ?></td> |
|||
<td><?php echo $item['creater']; ?></td> |
|||
<td><?php echo $item['create_at']; ?></td> |
|||
<td> |
|||
<?php |
|||
if($item['status'] == 'YY'){ |
|||
echo "結案同意"; |
|||
}elseif($item['status'] == 'YS'){ |
|||
echo "簽核中"; |
|||
}elseif($item['status'] == 'Y1'){ |
|||
echo "暫存"; |
|||
}elseif($item['status'] == 'YN'){ |
|||
echo "結案不同意"; |
|||
}else{ |
|||
echo "---"; |
|||
} |
|||
?> |
|||
</td> |
|||
|
|||
</tr> |
|||
<?php endforeach; ?> |
|||
</table> |
|||
|
|||
<script src="table2excel/dist/table2excel.min.js"></script> |
|||
<script> |
|||
const table2Excel = new Table2Excel('table') // new Table2Excel('table') |
|||
table2Excel.export('汰改價審明細', 'xlsx') // table2Excel.export('my-exported-table', 'xlsx') |
|||
</script> |
@ -0,0 +1,69 @@ |
|||
<?php |
|||
|
|||
require_once "./conn.php"; |
|||
|
|||
// $sql_str = "SELECT pricereview_main.*, account.name AS person_name FROM pricereview_main |
|||
// LEFT JOIN account ON account.accountid = pricereview_main.person |
|||
// WHERE pricereview_main.status <> 'D' |
|||
// AND pricereview_main.create_at >= '2024-01-01' |
|||
// AND pricereview_main.create_at <= '2024-01-31' |
|||
// AND ekind = '汰改'"; |
|||
// $stmt = $conn->prepare($sql_str); |
|||
// // $stmt->bindParam(':vol_no', $vol_no); |
|||
// $stmt->execute(); |
|||
// $result = $stmt->fetchAll(PDO::FETCH_ASSOC); |
|||
|
|||
|
|||
$sql_str = "SELECT con_maintance_examine_apply.*, account.name AS person_name, con_maintance_examine_clear.* FROM con_maintance_examine_apply |
|||
LEFT JOIN con_maintance_examine_clear ON con_maintance_examine_clear.apply_key = con_maintance_examine_apply.apply_key |
|||
LEFT JOIN account ON account.accountid = con_maintance_examine_apply.salesman |
|||
WHERE con_maintance_examine_apply.create_at >= '2024-01-01' AND con_maintance_examine_apply.create_at <= '2024-01-31'"; |
|||
$stmt = $conn->prepare($sql_str); |
|||
// $stmt->bindParam(':vol_no', $vol_no); |
|||
$stmt->execute(); |
|||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); |
|||
|
|||
?> |
|||
|
|||
|
|||
<table border=1> |
|||
<tr> |
|||
<th>ID</th> |
|||
<th>卷號</th> |
|||
<th>營業員</th> |
|||
<th>客戶名稱</th> |
|||
<th>案件名稱</th> |
|||
<th>標準價</th> |
|||
<th>售價總額</th> |
|||
<th>契約成交價</th> |
|||
<th>保養月數</th> |
|||
<th>建檔人</th> |
|||
<th>建檔時間</th> |
|||
<th>狀態</th> |
|||
</tr> |
|||
<?php foreach($result as $key=>$item): ?> |
|||
<tr> |
|||
<td><?php echo $key+1; ?></td> |
|||
<td><?php echo $item['vol_no']; ?></td> |
|||
<td><?php echo $item['person_name']; ?></td> |
|||
<td><?php echo $item['customer']; ?></td> |
|||
<td><?php echo $item['case_name']; ?></td> |
|||
<td><?php echo $item['stand_price']; ?></td> |
|||
<td><?php echo $item['contract_price']; ?></td> |
|||
<td><?php echo $item['sold_price']; ?></td> |
|||
<td><?php echo $item['maintain_months'] . '月'; ?></td> |
|||
<td><?php echo $item['creater']; ?></td> |
|||
<td><?php echo $item['create_at']; ?></td> |
|||
<td> |
|||
簽核中 |
|||
</td> |
|||
|
|||
</tr> |
|||
<?php endforeach; ?> |
|||
</table> |
|||
|
|||
<script src="table2excel/dist/table2excel.min.js"></script> |
|||
<script> |
|||
const table2Excel = new Table2Excel('table') // new Table2Excel('table') |
|||
table2Excel.export('保養價審', 'xlsx') // table2Excel.export('my-exported-table', 'xlsx') |
|||
</script> |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
@ -0,0 +1,6 @@ |
|||
{ |
|||
"presets":[ |
|||
"es2015", |
|||
"stage-1" |
|||
] |
|||
} |
@ -0,0 +1,58 @@ |
|||
# Logs |
|||
logs |
|||
*.log |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
|
|||
# Runtime data |
|||
pids |
|||
*.pid |
|||
*.seed |
|||
*.pid.lock |
|||
|
|||
# Directory for instrumented libs generated by jscoverage/JSCover |
|||
lib-cov |
|||
|
|||
# Coverage directory used by tools like istanbul |
|||
coverage |
|||
|
|||
# nyc test coverage |
|||
.nyc_output |
|||
|
|||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) |
|||
.grunt |
|||
|
|||
# Bower dependency directory (https://bower.io/) |
|||
bower_components |
|||
|
|||
# node-waf configuration |
|||
.lock-wscript |
|||
|
|||
# Compiled binary addons (http://nodejs.org/api/addons.html) |
|||
build/Release |
|||
|
|||
# Dependency directories |
|||
node_modules/ |
|||
jspm_packages/ |
|||
|
|||
# Typescript v1 declaration files |
|||
typings/ |
|||
|
|||
# Optional npm cache directory |
|||
.npm |
|||
|
|||
# Optional eslint cache |
|||
.eslintcache |
|||
|
|||
# Optional REPL history |
|||
.node_repl_history |
|||
|
|||
# Output of 'npm pack' |
|||
*.tgz |
|||
|
|||
# Yarn Integrity file |
|||
.yarn-integrity |
|||
|
|||
# dotenv environment variables file |
|||
.env |
@ -0,0 +1,192 @@ |
|||
# Table2Excel.js |
|||
|
|||
This is a library to export html tables to excel sheets. |
|||
|
|||
## Precondition |
|||
|
|||
It has to be a row * column table |
|||
|
|||
## Features |
|||
|
|||
1. able to export with width, alignment and colors |
|||
2. extendable |
|||
|
|||
## Dependencies |
|||
|
|||
[ExcelJS](https://github.com/guyonroche/exceljs) |
|||
|
|||
[FileSaver.js](https://github.com/eligrey/FileSaver.js) |
|||
|
|||
## Live Demo |
|||
|
|||
[Demo](https://jackgit.github.io/table2excel.js/index.html) |
|||
|
|||
## Include table2excel.js |
|||
|
|||
### npm |
|||
|
|||
`ExcelJS` is peer dependency to `table2excel.js`, so you need to install exceljs first: |
|||
|
|||
```bash |
|||
npm i exceljs |
|||
``` |
|||
|
|||
then, install table2excel.js: |
|||
|
|||
```bash |
|||
npm i table2excel.js |
|||
``` |
|||
|
|||
use in your code like: |
|||
|
|||
```js |
|||
import Table2Excel from 'table2excel.js' |
|||
new Table2Excel('table').export() |
|||
``` |
|||
|
|||
you may also need a config in webpack: |
|||
|
|||
```js |
|||
node: { fs: 'empty' } |
|||
``` |
|||
|
|||
### table2excel.min.js (with ExcelJS packed) |
|||
|
|||
```html |
|||
<script src="path/to/table2excel.min.js"></script> |
|||
``` |
|||
|
|||
### table2excel.core.js (without ExcelJS packed) |
|||
|
|||
```html |
|||
<script src="path/to/exceljs.min.js"></script> |
|||
<script src="path/to/table2excel.core.js"></script> |
|||
``` |
|||
|
|||
## Basic Usage |
|||
|
|||
```js |
|||
const table2Excel = new Table2Excel(selector, options) // new Table2Excel('table') |
|||
table2Excel.export(fileName, extension) // table2Excel.export('my-exported-table', 'xlsx') |
|||
``` |
|||
|
|||
`extension` can be `'xls'` or `'xlsx'`, default as `'xlsx'` |
|||
|
|||
### selector |
|||
|
|||
It's optional, and defaulted as `'table'` |
|||
|
|||
### options |
|||
|
|||
It's optional, and defaulted as: |
|||
|
|||
```js |
|||
{ |
|||
workbook: { |
|||
views: [{ |
|||
x: 0, y: 0, width: 10000, height: 20000, |
|||
firstSheet: 0, activeTab: 1, visibility: 'visible' |
|||
}] |
|||
}, |
|||
widthRatio: .14, |
|||
plugins: [ |
|||
Table2Excel.plugins.fontPlugin, |
|||
Table2Excel.plugins.fillPlugin, |
|||
Table2Excel.plugins.formPlugin, |
|||
Table2Excel.plugins.alignmentPlugin, |
|||
Table2Excel.plugins.hyperlinkPlugin, |
|||
Table2Excel.plugins.autoWidthPlugin |
|||
] |
|||
} |
|||
``` |
|||
|
|||
`workbook` is options used while creating a workbook, please refer [exceljs#create-a-workbook](https://github.com/guyonroche/exceljs#create-a-workbook) for details. |
|||
|
|||
`widthRatio` is a ratio that will be used while converting `width` style of html table cells to width of sheet cells. |
|||
|
|||
## Plugins |
|||
|
|||
Plugin helps to extend the ability of transforming table to excel. |
|||
|
|||
Build-in plugins can be access like: |
|||
|
|||
```js |
|||
Table2Excel.plugins.fontPlugin, |
|||
Table2Excel.plugins.fillPlugin, |
|||
Table2Excel.plugins.formPlugin, |
|||
Table2Excel.plugins.alignmentPlugin, |
|||
Table2Excel.plugins.hyperlinkPlugin, |
|||
Table2Excel.plugins.autoWidthPlugin |
|||
``` |
|||
|
|||
A plugin can be defined to join different phase of table to excel process, and in different phase, plugin is able to access different objects from context. |
|||
|
|||
```js |
|||
{ |
|||
/** |
|||
* after an empty workbook created |
|||
* @param {ExcelJS.Workbook} context.workbook |
|||
* @param {NodeList} context.tables |
|||
*/ |
|||
workbookCreated ({ workbook, tables }) {}, |
|||
/** |
|||
* after an empty worksheet created |
|||
* @param {ExcelJS.Workbook} workbook |
|||
* @param {NodeList} tables |
|||
* @param {ExcelJS.Worksheet} worksheet |
|||
* @param {HTMLTableElement} table |
|||
*/ |
|||
worksheetCreated ({ workbook, tables, worksheet, table }) {}, |
|||
/** |
|||
* after a worksheet been filled with data from table |
|||
* @param {ExcelJS.Workbook} workbook |
|||
* @param {NodeList} tables |
|||
* @param {ExcelJS.Worksheet} worksheet |
|||
* @param {HTMLTableElement} table |
|||
*/ |
|||
worksheetCompleted ({ workbook, tables, worksheet, table }) {}, |
|||
/** |
|||
* after an cell of worksheet created |
|||
* @param {ExcelJS.Workbook} workbook |
|||
* @param {NodeList} tables |
|||
* @param {ExcelJS.Worksheet} worksheet |
|||
* @param {HTMLTableElement} table |
|||
* @param {ExcelJS.Cell} workcell |
|||
* @param {HTMLTableCellElement} cell |
|||
* @param {colRange} [from, to] |
|||
* @param {rowRange} [from, to] |
|||
*/ |
|||
workcellCreated ({ workbook, tables, worksheet, table, workcell, cell, cellStyle, colRange, rowRange }) {} |
|||
} |
|||
``` |
|||
|
|||
|
|||
Example 1, you can define a plugin to make some rows or columns hidden of exported excel: |
|||
|
|||
```js |
|||
const table2Excel = new Table2Excel('table', { |
|||
plugins: [{ |
|||
worksheetCompleted ({ workbook, tables, worksheet, table }) { |
|||
worksheet.getRow(1).hidden = true |
|||
worksheet.getColumn(1).hidden = true |
|||
} |
|||
}] |
|||
}) |
|||
``` |
|||
|
|||
Example 2, you can add your customized cell parser for your table: |
|||
|
|||
```js |
|||
const table2Excel = new Table2Excel('table', { |
|||
plugins: [{ |
|||
workcellCreated ({ workbook, tables, worksheet, table, workcell, cell, cellStyle, rowRange, colRange }) { |
|||
workcell.value = { text: '', link: '' } |
|||
workcell.style = { |
|||
...workcell.style, |
|||
font: {}, |
|||
color: {} |
|||
} |
|||
} |
|||
}] |
|||
}) |
|||
``` |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,11 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
var MIME_TYPES = exports.MIME_TYPES = { |
|||
xls: 'application/vnd.ms-excel', |
|||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|||
}; |
|||
|
|||
var WIDTH_RATIO = exports.WIDTH_RATIO = .14; |
@ -0,0 +1,26 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
|
|||
var _table2excel = require('./table2excel'); |
|||
|
|||
var _table2excel2 = _interopRequireDefault(_table2excel); |
|||
|
|||
var _plugins = require('./plugins'); |
|||
|
|||
var _plugins2 = _interopRequireDefault(_plugins); |
|||
|
|||
var _utils = require('./utils'); |
|||
|
|||
var utils = _interopRequireWildcard(_utils); |
|||
|
|||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } |
|||
|
|||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
|||
|
|||
_table2excel2.default.plugins = _plugins2.default; |
|||
_table2excel2.default.utils = utils; |
|||
|
|||
exports.default = _table2excel2.default; |
@ -0,0 +1,62 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
|
|||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; |
|||
|
|||
/** |
|||
* '-webkit-right' -> 'right' |
|||
* 'right' -> 'right' |
|||
* etc... |
|||
*/ |
|||
var getHorizontalAlign = function getHorizontalAlign() { |
|||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; |
|||
|
|||
var aligns = ['right', 'left', 'center', 'justify']; |
|||
for (var i = 0; i < aligns.length; i++) { |
|||
if (value.includes(aligns[i])) { |
|||
return aligns[i]; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* 'baseline' -> 'middle' |
|||
* 'text-top' -> 'top' |
|||
* 'text-bottom' -> 'bottom' |
|||
* 'sub' -> 'top' |
|||
* 'super' -> 'bottom' |
|||
*/ |
|||
var getVerticalAlign = function getVerticalAlign() { |
|||
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; |
|||
|
|||
var aligns = ['top', 'middle', 'bottom']; |
|||
for (var i = 0; i < aligns.length; i++) { |
|||
if (value.includes(aligns[i])) { |
|||
return aligns[i]; |
|||
} |
|||
} |
|||
|
|||
var mapping = { |
|||
'baseline': 'middle', |
|||
'super': 'top', |
|||
'sub': 'bottom' |
|||
}; |
|||
return mapping[value]; |
|||
}; |
|||
|
|||
exports.default = { |
|||
workcellCreated: function workcellCreated(_ref) { |
|||
var workcell = _ref.workcell, |
|||
cellStyle = _ref.cellStyle; |
|||
var verticalAlign = cellStyle.verticalAlign, |
|||
textAlign = cellStyle.textAlign; |
|||
|
|||
workcell.alignment = _extends({}, workcell.alignment || {}, { |
|||
vertical: getVerticalAlign(verticalAlign), |
|||
horizontal: getHorizontalAlign(textAlign) |
|||
}); |
|||
} |
|||
}; |
@ -0,0 +1,17 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
exports.default = { |
|||
workcellCreated: function workcellCreated(_ref) { |
|||
var worksheet = _ref.worksheet, |
|||
colRange = _ref.colRange, |
|||
cell = _ref.cell, |
|||
cellStyle = _ref.cellStyle; |
|||
|
|||
if (colRange.from === colRange.to && cellStyle.width !== 'auto') { |
|||
worksheet.getColumn(colRange.from + 1).width = +cellStyle.width.split('px')[0] * this.options.widthRatio; |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,32 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
|
|||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; |
|||
|
|||
var _utils = require('../utils'); |
|||
|
|||
exports.default = { |
|||
workcellCreated: function workcellCreated(_ref) { |
|||
var workcell = _ref.workcell, |
|||
cellStyle = _ref.cellStyle; |
|||
|
|||
var color = (0, _utils.argb)(cellStyle.backgroundColor); |
|||
|
|||
if (color === '00000000') { |
|||
// background is transparent, equals none pattern fill
|
|||
workcell.fill = _extends({}, workcell.fill || {}, { |
|||
type: 'pattern', |
|||
pattern: 'none' |
|||
}); |
|||
} else { |
|||
workcell.fill = _extends({}, workcell.fill || {}, { |
|||
type: 'pattern', |
|||
pattern: 'solid', |
|||
fgColor: { argb: color } |
|||
}); |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,24 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
|
|||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; |
|||
|
|||
var _utils = require('../utils'); |
|||
|
|||
exports.default = { |
|||
workcellCreated: function workcellCreated(_ref) { |
|||
var workcell = _ref.workcell, |
|||
cellStyle = _ref.cellStyle; |
|||
|
|||
var fontWeight = cellStyle.fontWeight; |
|||
|
|||
workcell.font = _extends({}, workcell.font || {}, { |
|||
name: cellStyle.fontFamily, |
|||
color: { argb: (0, _utils.argb)(cellStyle.color) }, |
|||
bold: fontWeight === 'bold' || +fontWeight > 600 ? true : false |
|||
}); |
|||
} |
|||
}; |
@ -0,0 +1,16 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
exports.default = { |
|||
workcellCreated: function workcellCreated(_ref) { |
|||
var workcell = _ref.workcell, |
|||
cell = _ref.cell; |
|||
|
|||
var child = cell.children[0]; |
|||
if (child && ['INPUT', 'SELECT', 'TEXTAREA'].includes(child.tagName)) { |
|||
workcell.value = child.value; |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,16 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
exports.default = { |
|||
workcellCreated: function workcellCreated(_ref) { |
|||
var workcell = _ref.workcell, |
|||
cell = _ref.cell; |
|||
|
|||
var child = cell.children[0]; |
|||
if (child && child.tagName === 'A') { |
|||
workcell.value = { text: child.innerText, hyperlink: child.href }; |
|||
} |
|||
} |
|||
}; |
@ -0,0 +1,40 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
|
|||
var _font = require('./font'); |
|||
|
|||
var _font2 = _interopRequireDefault(_font); |
|||
|
|||
var _fill = require('./fill'); |
|||
|
|||
var _fill2 = _interopRequireDefault(_fill); |
|||
|
|||
var _form = require('./form'); |
|||
|
|||
var _form2 = _interopRequireDefault(_form); |
|||
|
|||
var _alignment = require('./alignment'); |
|||
|
|||
var _alignment2 = _interopRequireDefault(_alignment); |
|||
|
|||
var _hyperlink = require('./hyperlink'); |
|||
|
|||
var _hyperlink2 = _interopRequireDefault(_hyperlink); |
|||
|
|||
var _autoWidth = require('./autoWidth'); |
|||
|
|||
var _autoWidth2 = _interopRequireDefault(_autoWidth); |
|||
|
|||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
|||
|
|||
exports.default = { |
|||
fontPlugin: _font2.default, |
|||
fillPlugin: _fill2.default, |
|||
formPlugin: _form2.default, |
|||
alignmentPlugin: _alignment2.default, |
|||
hyperlinkPlugin: _hyperlink2.default, |
|||
autoWidthPlugin: _autoWidth2.default |
|||
}; |
@ -0,0 +1,202 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
|
|||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); |
|||
|
|||
var _exceljs = require('exceljs/dist/es5/exceljs.browser'); |
|||
|
|||
var _exceljs2 = _interopRequireDefault(_exceljs); |
|||
|
|||
var _utils = require('./utils'); |
|||
|
|||
var _constants = require('./constants'); |
|||
|
|||
var _plugins = require('./plugins'); |
|||
|
|||
var _plugins2 = _interopRequireDefault(_plugins); |
|||
|
|||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
|||
|
|||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } |
|||
|
|||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } |
|||
|
|||
var PLUGIN_FUNCS = ['workbookCreated', 'worksheetCreated', 'worksheetCompleted', 'workcellCreated']; |
|||
var DEFAULT_WORKBOOK_OPTIONS = { |
|||
views: [{ |
|||
x: 0, y: 0, width: 10000, height: 20000, |
|||
firstSheet: 0, activeTab: 1, visibility: 'visible' |
|||
}] |
|||
}; |
|||
var DEFAULT_OPTIONS = { |
|||
workbook: DEFAULT_WORKBOOK_OPTIONS, |
|||
widthRatio: _constants.WIDTH_RATIO, |
|||
plugins: [].concat(_toConsumableArray(Object.values(_plugins2.default))) |
|||
}; |
|||
|
|||
var Table2Excel = function () { |
|||
function Table2Excel() { |
|||
var _this = this; |
|||
|
|||
var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'table'; |
|||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; |
|||
|
|||
_classCallCheck(this, Table2Excel); |
|||
|
|||
this.tables = Array.from(typeof selector === 'string' ? document.querySelectorAll(selector) : selector); |
|||
|
|||
this.options = Object.assign({}, DEFAULT_OPTIONS, options); |
|||
|
|||
this.plugins = {}; |
|||
PLUGIN_FUNCS.forEach(function (funName) { |
|||
_this.plugins[funName] = _this.options.plugins.filter(function (plugin) { |
|||
return plugin[funName]; |
|||
}).map(function (plugin) { |
|||
return plugin[funName]; |
|||
}); |
|||
}); |
|||
|
|||
this.pluginContext = {}; |
|||
} |
|||
|
|||
_createClass(Table2Excel, [{ |
|||
key: '_invokePlugin', |
|||
value: function _invokePlugin(func) { |
|||
var _this2 = this; |
|||
|
|||
var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; |
|||
|
|||
this.pluginContext = Object.assign({}, this.pluginContext, context); |
|||
this.plugins[func].forEach(function (handler) { |
|||
return handler.call(_this2, _this2.pluginContext); |
|||
}); |
|||
} |
|||
}, { |
|||
key: 'toExcel', |
|||
value: function toExcel() { |
|||
var _this3 = this; |
|||
|
|||
var tables = this.tables, |
|||
options = this.options; |
|||
|
|||
var workbook = new _exceljs2.default.Workbook(); // create workbook
|
|||
|
|||
Object.assign(workbook, options); |
|||
|
|||
// workbookCreated plugins
|
|||
this._invokePlugin('workbookCreated', { workbook: workbook, tables: tables }); |
|||
|
|||
tables.forEach(function (table, index) { |
|||
var worksheet = workbook.addWorksheet('Sheet ' + (index + 1)); |
|||
|
|||
// worksheetCreated plugins
|
|||
_this3._invokePlugin('worksheetCreated', { worksheet: worksheet, table: table }); |
|||
|
|||
_this3.toSheet(table, worksheet); |
|||
|
|||
// worksheetCompleted plugins
|
|||
_this3._invokePlugin('worksheetCompleted', { worksheet: worksheet, table: table }); |
|||
}); |
|||
|
|||
return this.workbook = workbook; |
|||
} |
|||
}, { |
|||
key: 'toSheet', |
|||
value: function toSheet(table, worksheet) { |
|||
var _this4 = this; |
|||
|
|||
// get total cols and rows
|
|||
var totalRows = table.rows.length; |
|||
var totalCols = 0; |
|||
|
|||
if (table.rows.length > 0) { |
|||
for (var i = 0; i < table.rows[0].cells.length; i++) { |
|||
totalCols += table.rows[0].cells[i].colSpan; |
|||
} |
|||
} |
|||
|
|||
var cells = []; |
|||
Array.from(table.rows).forEach(function (row) { |
|||
Array.from(row.cells).forEach(function (cell) { |
|||
cells.push({ |
|||
rowRange: {}, |
|||
colRange: {}, |
|||
el: cell |
|||
}); |
|||
}); |
|||
}); |
|||
|
|||
// create matrix
|
|||
var helperMatrix = []; |
|||
|
|||
for (var r = 0; r < totalRows; r++) { |
|||
var row = []; |
|||
for (var c = 0; c < totalCols; c++) { |
|||
row.push({ cell: null }); |
|||
} |
|||
helperMatrix.push(row); |
|||
} |
|||
|
|||
// mark matrix
|
|||
var cursor = 0; |
|||
|
|||
for (var _r = 0; _r < totalRows; _r++) { |
|||
for (var _c = 0; _c < totalCols; _c++) { |
|||
// skip if current matrix unit is already assigned
|
|||
if (helperMatrix[_r][_c].cell) { |
|||
continue; |
|||
} |
|||
|
|||
// assign cell to current matrix unit
|
|||
var cell = cells[cursor++]; |
|||
var _cell$el = cell.el, |
|||
rowSpan = _cell$el.rowSpan, |
|||
colSpan = _cell$el.colSpan; |
|||
|
|||
|
|||
cell.rowRange = { from: _r, to: _r }; |
|||
cell.colRange = { from: _c, to: _c }; |
|||
|
|||
for (var y = _r; y < _r + rowSpan; y++) { |
|||
for (var x = _c; x < _c + colSpan; x++) { |
|||
helperMatrix[y][x].cell = cell; |
|||
cell.colRange.to = x; |
|||
cell.rowRange.to = y; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// read matrix to sheet
|
|||
cells.forEach(function (cell) { |
|||
var rowRange = cell.rowRange, |
|||
colRange = cell.colRange, |
|||
el = cell.el; |
|||
var innerText = el.innerText; |
|||
|
|||
var workcell = (0, _utils.mergeCells)(worksheet, colRange.from, rowRange.from, colRange.to, rowRange.to); |
|||
var cellStyle = getComputedStyle(el); |
|||
|
|||
workcell.value = innerText; |
|||
|
|||
// workcellCreated
|
|||
_this4._invokePlugin('workcellCreated', { workcell: workcell, cell: el, rowRange: rowRange, colRange: colRange, cellStyle: cellStyle }); |
|||
}); |
|||
} |
|||
}, { |
|||
key: 'export', |
|||
value: function _export(fileName, ext) { |
|||
if (!this.workbook) { |
|||
this.toExcel(); |
|||
} |
|||
(0, _utils.saveAsExcel)(this.workbook, fileName, ext); |
|||
} |
|||
}]); |
|||
|
|||
return Table2Excel; |
|||
}(); |
|||
|
|||
exports.default = Table2Excel; |
@ -0,0 +1,89 @@ |
|||
'use strict'; |
|||
|
|||
Object.defineProperty(exports, "__esModule", { |
|||
value: true |
|||
}); |
|||
exports.argb = exports.mergeCells = exports.cellPosition = exports.columnIndex = exports.saveAsExcel = undefined; |
|||
|
|||
var _constants = require('./constants'); |
|||
|
|||
var _fileSaver = require('file-saver'); |
|||
|
|||
var saveAsExcel = exports.saveAsExcel = function saveAsExcel(workbook) { |
|||
var filename = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'table'; |
|||
var ext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'xlsx'; |
|||
|
|||
var type = _constants.MIME_TYPES[ext]; |
|||
|
|||
if (!type) { |
|||
console.error(ext + ' file extension is not supported'); |
|||
return; |
|||
} |
|||
|
|||
workbook.xlsx.writeBuffer().then(function (uint8) { |
|||
(0, _fileSaver.saveAs)(new Blob([uint8.buffer], { type: type }), filename + '.' + ext); |
|||
}); |
|||
}; |
|||
|
|||
var letter = function letter(num) { |
|||
var a = 'A'.charCodeAt(0); |
|||
return String.fromCharCode(a + num - 1); |
|||
}; |
|||
|
|||
/** |
|||
* 0 => A |
|||
* 25 => Z |
|||
* 26 => AA |
|||
*/ |
|||
var columnIndex = exports.columnIndex = function columnIndex(num) { |
|||
var result = void 0; |
|||
num = num + 1; |
|||
|
|||
if (num <= 26) { |
|||
result = letter(num); |
|||
} else { |
|||
var mod = num % 26; |
|||
var quotient = Math.floor(num / 26); |
|||
|
|||
if (mod === 0) { |
|||
result = letter(quotient - 1) + letter(26); |
|||
} else { |
|||
result = letter(quotient) + letter(mod); |
|||
} |
|||
} |
|||
return result; |
|||
}; |
|||
|
|||
// x = 0, y = 0 => 'A1'
|
|||
// x = 0, y = 1 => 'A2'
|
|||
// x = 1, y = 0 => 'B1'
|
|||
var cellPosition = exports.cellPosition = function cellPosition(x, y) { |
|||
return '' + columnIndex(x) + (y + 1); |
|||
}; |
|||
|
|||
var mergeCells = exports.mergeCells = function mergeCells(sheet, x1, y1, x2, y2) { |
|||
var fromCell = cellPosition(x1, y1); |
|||
var toCell = cellPosition(x2, y2); |
|||
sheet.mergeCells(fromCell, toCell); |
|||
return sheet.getCell(fromCell); |
|||
}; |
|||
|
|||
/** |
|||
* convert rgb(0,0,0) rgba(0,0,0,0) to argb: FF00FF00 |
|||
*/ |
|||
var argb = exports.argb = function argb(color) { |
|||
var values = color.split('(')[1].split(')')[0].split(',').map(function (v, i) { |
|||
return i === 3 ? v * 255 : v; |
|||
}); |
|||
|
|||
if (values.length === 3) { |
|||
values.push(255); |
|||
} |
|||
|
|||
values.unshift(values.pop()); |
|||
|
|||
return values.map(function (v) { |
|||
var s = parseInt(v).toString(16); |
|||
return s.length === 1 ? '0' + s : s; |
|||
}).join('').toUpperCase(); |
|||
}; |
@ -0,0 +1,42 @@ |
|||
{ |
|||
"name": "table2excel.js", |
|||
"version": "1.0.0", |
|||
"description": "", |
|||
"main": "es5/index.js", |
|||
"scripts": { |
|||
"test": "echo \"Error: no test specified\" && exit 1", |
|||
"build": "webpack --config webpack.core.config.js -p && webpack --config webpack.umd.config.js -p", |
|||
"build:es5": "babel src --out-dir es5" |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/jackgit/table2excel.js.git" |
|||
}, |
|||
"keywords": [ |
|||
"table", |
|||
"js", |
|||
"excel", |
|||
"xlsx", |
|||
"xls" |
|||
], |
|||
"author": "ygjack414@hotmail.com", |
|||
"license": "MIT", |
|||
"bugs": { |
|||
"url": "https://github.com/jackgit/table2excel.js/issues" |
|||
}, |
|||
"homepage": "https://github.com/jackgit/table2excel.js#readme", |
|||
"dependencies": { |
|||
"file-saver": "^1.3.3" |
|||
}, |
|||
"peerDependencies": { |
|||
"exceljs": "^0.6.2" |
|||
}, |
|||
"devDependencies": { |
|||
"babel-cli": "^6.26.0", |
|||
"babel-core": "^6.26.0", |
|||
"babel-loader": "^7.1.2", |
|||
"babel-preset-es2015": "^6.24.1", |
|||
"babel-preset-stage-1": "^6.24.1", |
|||
"cross-env": "^5.2.0" |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
export const MIME_TYPES = { |
|||
xls: 'application/vnd.ms-excel', |
|||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|||
} |
|||
|
|||
export const WIDTH_RATIO = .14 |
@ -0,0 +1,8 @@ |
|||
import Table2Excel from './table2excel' |
|||
import plugins from './plugins' |
|||
import * as utils from './utils' |
|||
|
|||
Table2Excel.plugins = plugins |
|||
Table2Excel.utils = utils |
|||
|
|||
export default Table2Excel |
@ -0,0 +1,49 @@ |
|||
/** |
|||
* '-webkit-right' -> 'right' |
|||
* 'right' -> 'right' |
|||
* etc... |
|||
*/ |
|||
const getHorizontalAlign = (value = '') => { |
|||
const aligns = ['right', 'left', 'center', 'justify'] |
|||
for (let i = 0; i < aligns.length; i++) { |
|||
if (value.includes(aligns[i])) { |
|||
return aligns[i] |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 'baseline' -> 'middle' |
|||
* 'text-top' -> 'top' |
|||
* 'text-bottom' -> 'bottom' |
|||
* 'sub' -> 'top' |
|||
* 'super' -> 'bottom' |
|||
*/ |
|||
const getVerticalAlign = (value = '') => { |
|||
const aligns = ['top', 'middle', 'bottom'] |
|||
for (let i = 0; i < aligns.length; i++) { |
|||
if (value.includes(aligns[i])) { |
|||
return aligns[i] |
|||
} |
|||
} |
|||
|
|||
const mapping = { |
|||
'baseline': 'middle', |
|||
'super': 'top', |
|||
'sub': 'bottom' |
|||
} |
|||
return mapping[value] |
|||
} |
|||
|
|||
export default { |
|||
workcellCreated ({ workcell, cellStyle }) { |
|||
const { verticalAlign, textAlign } = cellStyle |
|||
workcell.alignment = { |
|||
...(workcell.alignment || {}), |
|||
...({ |
|||
vertical: getVerticalAlign(verticalAlign), |
|||
horizontal: getHorizontalAlign(textAlign) |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,7 @@ |
|||
export default { |
|||
workcellCreated ({ worksheet, colRange, cell, cellStyle }) { |
|||
if (colRange.from === colRange.to && cellStyle.width !== 'auto') { |
|||
worksheet.getColumn(colRange.from + 1).width = (+cellStyle.width.split('px')[0]) * this.options.widthRatio |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,27 @@ |
|||
import { argb } from '../utils' |
|||
|
|||
export default { |
|||
workcellCreated ({ workcell, cellStyle }) { |
|||
const color = argb(cellStyle.backgroundColor) |
|||
|
|||
if (color === '00000000') { |
|||
// background is transparent, equals none pattern fill
|
|||
workcell.fill = { |
|||
...(workcell.fill || {}), |
|||
...({ |
|||
type: 'pattern', |
|||
pattern: 'none' |
|||
}) |
|||
} |
|||
} else { |
|||
workcell.fill = { |
|||
...(workcell.fill || {}), |
|||
...({ |
|||
type: 'pattern', |
|||
pattern: 'solid', |
|||
fgColor: { argb: color } |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
import { argb } from '../utils' |
|||
|
|||
export default { |
|||
workcellCreated ({ workcell, cellStyle }) { |
|||
const fontWeight = cellStyle.fontWeight |
|||
|
|||
workcell.font = { |
|||
...(workcell.font || {}), |
|||
...({ |
|||
name: cellStyle.fontFamily, |
|||
color: { argb: argb(cellStyle.color) }, |
|||
bold: (fontWeight === 'bold' || +fontWeight > 600) ? true : false |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,8 @@ |
|||
export default { |
|||
workcellCreated ({ workcell, cell }) { |
|||
const child = cell.children[0] |
|||
if (child && ['INPUT', 'SELECT', 'TEXTAREA'].includes(child.tagName)) { |
|||
workcell.value = child.value |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,8 @@ |
|||
export default { |
|||
workcellCreated ({ workcell, cell }) { |
|||
const child = cell.children[0] |
|||
if (child && child.tagName === 'A') { |
|||
workcell.value = { text: child.innerText, hyperlink: child.href } |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
import fontPlugin from './font' |
|||
import fillPlugin from './fill' |
|||
import formPlugin from './form' |
|||
import alignmentPlugin from './alignment' |
|||
import hyperlinkPlugin from './hyperlink' |
|||
import autoWidthPlugin from './autoWidth' |
|||
|
|||
export default { |
|||
fontPlugin, |
|||
fillPlugin, |
|||
formPlugin, |
|||
alignmentPlugin, |
|||
hyperlinkPlugin, |
|||
autoWidthPlugin |
|||
} |
@ -0,0 +1,149 @@ |
|||
import ExcelJS from 'exceljs/dist/es5/exceljs.browser' |
|||
import { mergeCells, saveAsExcel } from './utils' |
|||
import { WIDTH_RATIO } from './constants' |
|||
import plugins from './plugins' |
|||
|
|||
const PLUGIN_FUNCS = ['workbookCreated', 'worksheetCreated', 'worksheetCompleted', 'workcellCreated'] |
|||
const DEFAULT_WORKBOOK_OPTIONS = { |
|||
views: [{ |
|||
x: 0, y: 0, width: 10000, height: 20000, |
|||
firstSheet: 0, activeTab: 1, visibility: 'visible' |
|||
}] |
|||
} |
|||
const DEFAULT_OPTIONS = { |
|||
workbook: DEFAULT_WORKBOOK_OPTIONS, |
|||
widthRatio: WIDTH_RATIO, |
|||
plugins: [...Object.values(plugins)] |
|||
} |
|||
|
|||
export default class Table2Excel { |
|||
|
|||
constructor (selector = 'table', options = {}) { |
|||
this.tables = Array.from( |
|||
typeof selector === 'string' |
|||
? document.querySelectorAll(selector) |
|||
: selector |
|||
) |
|||
|
|||
this.options = Object.assign({}, DEFAULT_OPTIONS, options) |
|||
|
|||
this.plugins = {} |
|||
PLUGIN_FUNCS.forEach(funName => { |
|||
this.plugins[funName] = this.options.plugins.filter(plugin => plugin[funName]).map(plugin => plugin[funName]) |
|||
}) |
|||
|
|||
this.pluginContext = {} |
|||
} |
|||
|
|||
_invokePlugin (func, context = {}) { |
|||
this.pluginContext = Object.assign({}, this.pluginContext, context) |
|||
this.plugins[func].forEach(handler => handler.call(this, this.pluginContext)) |
|||
} |
|||
|
|||
toExcel () { |
|||
const { tables, options } = this |
|||
const workbook = new ExcelJS.Workbook() // create workbook
|
|||
|
|||
Object.assign(workbook, options) |
|||
|
|||
// workbookCreated plugins
|
|||
this._invokePlugin('workbookCreated', { workbook, tables }) |
|||
|
|||
tables.forEach((table, index) => { |
|||
const worksheet = workbook.addWorksheet(`Sheet ${index + 1}`) |
|||
|
|||
// worksheetCreated plugins
|
|||
this._invokePlugin('worksheetCreated', { worksheet, table }) |
|||
|
|||
this.toSheet(table, worksheet) |
|||
|
|||
// worksheetCompleted plugins
|
|||
this._invokePlugin('worksheetCompleted', { worksheet, table }) |
|||
}) |
|||
|
|||
return this.workbook = workbook |
|||
} |
|||
|
|||
toSheet (table, worksheet) { |
|||
// get total cols and rows
|
|||
const totalRows = table.rows.length |
|||
let totalCols = 0 |
|||
|
|||
if (table.rows.length > 0) { |
|||
for (let i = 0; i < table.rows[0].cells.length; i++) { |
|||
totalCols += table.rows[0].cells[i].colSpan |
|||
} |
|||
} |
|||
|
|||
const cells = [] |
|||
Array.from(table.rows).forEach(row => { |
|||
Array.from(row.cells).forEach(cell => { |
|||
cells.push({ |
|||
rowRange: {}, |
|||
colRange: {}, |
|||
el: cell |
|||
}) |
|||
}) |
|||
}) |
|||
|
|||
// create matrix
|
|||
const helperMatrix = [] |
|||
|
|||
for (let r = 0; r < totalRows; r++) { |
|||
const row = [] |
|||
for (let c = 0; c < totalCols; c++) { |
|||
row.push({ cell: null }) |
|||
} |
|||
helperMatrix.push(row) |
|||
} |
|||
|
|||
|
|||
// mark matrix
|
|||
let cursor = 0 |
|||
|
|||
for (let r = 0; r < totalRows; r++) { |
|||
for (let c = 0; c < totalCols; c++) { |
|||
// skip if current matrix unit is already assigned
|
|||
if (helperMatrix[r][c].cell) { |
|||
continue |
|||
} |
|||
|
|||
// assign cell to current matrix unit
|
|||
const cell = cells[cursor++] |
|||
const { rowSpan, colSpan } = cell.el |
|||
|
|||
cell.rowRange = { from: r, to: r } |
|||
cell.colRange = { from: c, to: c } |
|||
|
|||
for (let y = r; y < r + rowSpan; y++) { |
|||
for (let x = c; x < c + colSpan; x++) { |
|||
helperMatrix[y][x].cell = cell |
|||
cell.colRange.to = x |
|||
cell.rowRange.to = y |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
// read matrix to sheet
|
|||
cells.forEach(cell => { |
|||
const { rowRange, colRange, el } = cell |
|||
const { innerText } = el |
|||
const workcell = mergeCells(worksheet, colRange.from, rowRange.from, colRange.to, rowRange.to) |
|||
const cellStyle = getComputedStyle(el) |
|||
|
|||
workcell.value = innerText |
|||
|
|||
// workcellCreated
|
|||
this._invokePlugin('workcellCreated', { workcell, cell: el, rowRange, colRange, cellStyle }) |
|||
}) |
|||
} |
|||
|
|||
export (fileName, ext) { |
|||
if (!this.workbook) { |
|||
this.toExcel() |
|||
} |
|||
saveAsExcel(this.workbook, fileName, ext) |
|||
} |
|||
} |
@ -0,0 +1,81 @@ |
|||
import { MIME_TYPES } from './constants' |
|||
import { saveAs } from 'file-saver' |
|||
|
|||
export const saveAsExcel = (workbook, filename = 'table', ext = 'xlsx') => { |
|||
const type = MIME_TYPES[ext] |
|||
|
|||
if (!type) { |
|||
console.error(`${ext} file extension is not supported`) |
|||
return |
|||
} |
|||
|
|||
workbook.xlsx.writeBuffer().then(uint8 => { |
|||
saveAs( |
|||
new Blob([uint8.buffer], { type }), |
|||
`${filename}.${ext}` |
|||
) |
|||
}) |
|||
} |
|||
|
|||
const letter = num => { |
|||
const a = 'A'.charCodeAt(0) |
|||
return String.fromCharCode(a + num - 1) |
|||
} |
|||
|
|||
/** |
|||
* 0 => A |
|||
* 25 => Z |
|||
* 26 => AA |
|||
*/ |
|||
export const columnIndex = num => { |
|||
let result |
|||
num = num + 1 |
|||
|
|||
if (num <= 26) { |
|||
result = letter(num) |
|||
} else { |
|||
const mod = num % 26 |
|||
const quotient = Math.floor(num / 26) |
|||
|
|||
if (mod === 0) { |
|||
result = letter(quotient - 1) + letter(26) |
|||
} else { |
|||
result = letter(quotient) + letter(mod) |
|||
} |
|||
} |
|||
return result |
|||
} |
|||
|
|||
// x = 0, y = 0 => 'A1'
|
|||
// x = 0, y = 1 => 'A2'
|
|||
// x = 1, y = 0 => 'B1'
|
|||
export const cellPosition = (x, y) => { |
|||
return `${columnIndex(x)}${y + 1}` |
|||
} |
|||
|
|||
export const mergeCells = (sheet, x1, y1, x2, y2) => { |
|||
const fromCell = cellPosition(x1, y1) |
|||
const toCell = cellPosition(x2, y2) |
|||
sheet.mergeCells(fromCell, toCell) |
|||
return sheet.getCell(fromCell) |
|||
} |
|||
|
|||
/** |
|||
* convert rgb(0,0,0) rgba(0,0,0,0) to argb: FF00FF00 |
|||
*/ |
|||
export const argb = color => { |
|||
const values = color |
|||
.split('(')[1].split(')')[0].split(',') |
|||
.map((v, i) => i === 3 ? v * 255 : v) |
|||
|
|||
if (values.length === 3) { |
|||
values.push(255) |
|||
} |
|||
|
|||
values.unshift(values.pop()) |
|||
|
|||
return values.map(v => { |
|||
const s = parseInt(v).toString(16) |
|||
return s.length === 1 ? `0${s}` : s |
|||
}).join('').toUpperCase() |
|||
} |
@ -0,0 +1,26 @@ |
|||
module.exports = { |
|||
entry: './src/index.js', |
|||
output: { |
|||
filename: './dist/table2excel.core.js', |
|||
library: 'Table2Excel', |
|||
libraryTarget: 'umd', |
|||
libraryExport: 'default' |
|||
}, |
|||
module: { |
|||
rules: [ |
|||
{ |
|||
test: /\.js$/, |
|||
use: [ |
|||
'babel-loader', |
|||
], |
|||
exclude: /node_modules/ |
|||
} |
|||
] |
|||
}, |
|||
externals: { |
|||
'exceljs/dist/es5/exceljs.browser': 'ExcelJS' |
|||
}, |
|||
node: { |
|||
fs: 'empty' |
|||
} |
|||
}; |
@ -0,0 +1,23 @@ |
|||
module.exports = { |
|||
entry: './src/index.js', |
|||
output: { |
|||
filename: './dist/table2excel.min.js', |
|||
library: 'Table2Excel', |
|||
libraryTarget: 'umd', |
|||
libraryExport: 'default' |
|||
}, |
|||
module: { |
|||
rules: [ |
|||
{ |
|||
test: /\.js$/, |
|||
use: [ |
|||
'babel-loader', |
|||
], |
|||
exclude: /node_modules/ |
|||
} |
|||
] |
|||
}, |
|||
node: { |
|||
fs: 'empty' |
|||
} |
|||
}; |
@ -0,0 +1,47 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.demolish" x-ref="createDemolishModal" id="createDemolishModal"> |
|||
<div class="window-modal-content modal-xl"> |
|||
<div class="window-modal-header"> |
|||
<h4>新增拆梯價格</h4> |
|||
<button class="btn btn-close" @click="hideCreateDemolishModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr class="table-active"> |
|||
<th>人乘/載重</th> |
|||
<th>樓層</th> |
|||
<th>單價</th> |
|||
<th>數量</th> |
|||
<th>總價</th> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<select class="form-control" x-model="modalDemolishOptionsInfo.person" @change="getModalDemolishPrice()"> |
|||
<option value="">請選擇</option> |
|||
<option value="15人(含)以下">15人(含)以下/1000KGS</option> |
|||
<option value="16~24人">16~24人/1001~1600KGS</option> |
|||
<option value="25~30人">25~30人/1601~2500KGS</option> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<select class="form-control" x-model="modalDemolishOptionsInfo.floor" @change="getModalDemolishPrice()"> |
|||
<option value="">請選擇</option> |
|||
<?php for($i=4;$i<=40;$i++): ?> |
|||
<option value="<?php echo $i; ?>"><?php echo $i; ?></option> |
|||
<?php endfor; ?> |
|||
</select> |
|||
</td> |
|||
<td><input type="text" disabled class="form-control" x-model="Number(modalDemolishOptionsInfo.price).toLocaleString()"></td> |
|||
<td><input type="number" class="form-control" x-model="modalDemolishOptionsInfo.qty"></td> |
|||
<td><input type="text" disabled class="form-control" x-model="(modalDemolishOptionsInfo.price * modalDemolishOptionsInfo.qty).toLocaleString()"></td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideCreateDemolishModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="createDemolishOptionFn()">新增</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideCreateDemolishModal()"></div> |
|||
</div> |
@ -0,0 +1,36 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.demolishToElevator" x-ref="toDemolishOptionElevatorModal" id="toDemolishOptionElevatorModal"> |
|||
<div class="window-modal-content modal-m"> |
|||
<div class="window-modal-header"> |
|||
<h4>配對電梯</h4> |
|||
<button class="btn btn-close" @click="hideToDemolishOptionElevatorModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr> |
|||
<th>項次</th> |
|||
<th>規格</th> |
|||
<th>選擇</th> |
|||
</tr> |
|||
<template x-for="elevator in toElevators"> |
|||
<tr> |
|||
<td x-text="elevator.id"></td> |
|||
<td x-text="elevator.model"></td> |
|||
<td><input type="radio" name="demolishOptionToElevator" :value="elevator.id" class="form-check-input" x-model="toElevatorNo" /></td> |
|||
</tr> |
|||
</template> |
|||
<tr x-show="toElevators.length == 0"> |
|||
<td colspan="3"> |
|||
<small class="text-danger" style="font-size:13px;font-weight:600">暫無可選電梯,請先新增電梯規格!</small> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideToDemolishOptionElevatorModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="chkDemolishOptionToElevators()">確認</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideToDemolishOptionElevatorModal()"></div> |
|||
</div> |
@ -0,0 +1,124 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.elevator" x-ref="createElevatorModal" id="createElevatorModal"> |
|||
<div class="window-modal-content modal-xl"> |
|||
<div class="window-modal-header"> |
|||
<h4>新增電梯規格</h4> |
|||
<button class="btn btn-close" @click="hideCreateElevatorModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr class="table-active"> |
|||
<th>電梯</th> |
|||
<th>人乘</th> |
|||
<th>載重(KG)</th> |
|||
<th>停數</th> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<select name="" id="" class="form-control" x-model="modalElevatorInfo.spec" @change="getModalElevatorPrice()"> |
|||
<option value="">請選擇</option> |
|||
<option value="MAE100">MAE100有機房</option> |
|||
<option value="MAM200">MAM200無機房</option> |
|||
<option value="MAH100">MAH100小電梯</option> |
|||
<option value="MAF100">MAF100貨梯(有機房)</option> |
|||
<option value="MAQ100">MAQ100強趨梯</option> |
|||
<option value="MAP100">MAP100平台梯</option> |
|||
<?php if($hope_customer['is_renovation'] == 'Y'): ?> |
|||
<option value="M1">M1(系統更新)</option> |
|||
<option value="M1+M4(1:1)">M1+M4(1:1)系統+主機</option> |
|||
<option value="M1+M4(2:1)">M1+M4(2:1)系統+主機</option> |
|||
<?php endif; ?> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<select name="" id="" class="form-control" x-model="modalElevatorInfo.person" @change="getModalElevatorPrice()"> |
|||
<option value="">請選擇</option> |
|||
<option value="6">6</option> |
|||
<option value="8">8</option> |
|||
<option value="9">9</option> |
|||
<option value="10">10</option> |
|||
<option value="11">11</option> |
|||
<option value="12">12</option> |
|||
<option value="13">13</option> |
|||
<option value="15">15</option> |
|||
<option value="17">17</option> |
|||
<option value="20">20</option> |
|||
<option value="24">24</option> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<input type="number" class="form-control" style="width:93px" x-model="modalElevatorInfo.weight" @keyup="getModalElevatorPrice()" @change="getModalElevatorPrice()"> |
|||
</td> |
|||
<td> |
|||
<input type="number" class="form-control" style="width:93px" x-model="modalElevatorInfo.stop" @keyup="getModalElevatorPrice()" @change="getModalElevatorPrice()" /> |
|||
</td> |
|||
|
|||
</tr> |
|||
<tr class="table-active"> |
|||
<th>開門方式</th> |
|||
<th>速度</th> |
|||
<th>規格</th> |
|||
<th>數量</th> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<select name="" id="" class="form-control" style="width:93px" x-model="modalElevatorInfo.open" @change="getModalElevatorPrice()"> |
|||
<option value="CO">CO</option> |
|||
<option value="2S">2S</option> |
|||
<option value="2U">CO</option> |
|||
<option value="4PCO">4PCO</option> |
|||
<option value="6PCO">6PCO</option> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<select name="" id="" class="form-control" style="width:93px" x-model="modalElevatorInfo.speed" @change="getModalElevatorPrice()" > |
|||
<option value="">請選擇</option> |
|||
<option value="9">9</option> |
|||
<option value="24">24</option> |
|||
<option value="30">30</option> |
|||
<option value="45">45</option> |
|||
<option value="60">60</option> |
|||
<option value="90">90</option> |
|||
<option value="105">105</option> |
|||
<option value="120">120</option> |
|||
<option value="150">150</option> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<input type="text" x-show="!modalElevatorInfo.price || modalElevatorInfo.price ==''" class="form-control" disabled /> |
|||
<input type="text" x-show="modalElevatorInfo.price > 0" class="form-control" disabled x-model="modalElevatorInfo.model"> |
|||
</td> |
|||
<td> |
|||
<input type="number" class="form-control" style="width:93px" x-model="modalElevatorInfo.num" > |
|||
</td> |
|||
</tr> |
|||
<tr class="table-active"> |
|||
<th>公司發布價(單價)</th> |
|||
<th>公司發布價(複價)</th> |
|||
<th>自定售價(台)</th> |
|||
<th>自定售價(總價)</th> |
|||
</tr> |
|||
<tr> |
|||
<td> |
|||
<input type="text" disabled class="form-control" x-model="(modalElevatorInfo.price).toLocaleString()"> |
|||
</td> |
|||
<td> |
|||
<input type="text" disabled class="form-control" x-model="(modalElevatorInfo.price * modalElevatorInfo.num).toLocaleString()"> |
|||
</td> |
|||
<td> |
|||
<input type="number" class="form-control" x-model="modalElevatorInfo.sale_price"> |
|||
</td> |
|||
<td> |
|||
<input type="text" disabled class="form-control" x-model="(modalElevatorInfo.sale_price * modalElevatorInfo.num).toLocaleString()"> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideCreateElevatorModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="createElevatorFn()">新增</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideCreateElevatorModal()"></div> |
|||
</div> |
@ -0,0 +1,62 @@ |
|||
<div class="window-modal " x-show="historySignShow" x-cloak data-type="window-modal" x-ref="historySign" id="historySign"> |
|||
<div class="window-modal-content modal-lg"> |
|||
<div class="window-modal-header"> |
|||
<h4>歷史簽核紀錄</h4> |
|||
<button class="btn btn-close" @click="hideHistorySignModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table historytable" style="width:700px"> |
|||
<thead> |
|||
<tr> |
|||
<th>審核</th> |
|||
<th>審核人</th> |
|||
<th>結果</th> |
|||
<th>意見</th> |
|||
<th>時間</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<?php foreach($historySign as $key=>$history): ?> |
|||
<tr> |
|||
<td colspan="5"></td> |
|||
</tr> |
|||
<tr> |
|||
<td>區經理</td> |
|||
<td><?php echo $history['signer1']; ?></td> |
|||
<td><?php echo $history['sign1_result']; ?></td> |
|||
<td><?php echo $history['sign1_note']; ?></td> |
|||
<td><?php echo $history['sign1_date']; ?></td> |
|||
</tr> |
|||
<tr> |
|||
<td x-text="is_renovate=='汰改' ? '服務助理' : '業務承辦人'"></td> |
|||
<td><?php echo $history['signer2']; ?></td> |
|||
<td><?php echo $history['sign2_result']; ?></td> |
|||
<td><?php echo $history['sign2_note']; ?></td> |
|||
<td><?php echo $history['sign2_date']; ?></td> |
|||
</tr> |
|||
<tr> |
|||
<td x-text="is_renovate=='汰改' ? '服務副總' :'業務部協理'"></td> |
|||
<td><?php echo $history['signer3']; ?></td> |
|||
<td><?php echo $history['sign3_result']; ?></td> |
|||
<td><?php echo $history['sign3_note']; ?></td> |
|||
<td><?php echo $history['sign3_date']; ?></td> |
|||
</tr> |
|||
<tr> |
|||
<td>總經理</td> |
|||
<td><?php echo $history['signer4']; ?></td> |
|||
<td><?php echo $history['sign4_result']; ?></td> |
|||
<td><?php echo $history['sign4_note']; ?></td> |
|||
<td><?php echo $history['sign4_date']; ?></td> |
|||
</tr> |
|||
<?php endforeach; ?> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @click="hideHistorySignModal()">關閉</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideHistorySignModal()"></div> |
|||
</div> |
@ -0,0 +1,31 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.maintain" x-ref="createMaintainModal" id="createMaintainModal"> |
|||
<div class="window-modal-content modal-xl"> |
|||
<div class="window-modal-header"> |
|||
<h4>新增保固延長</h4> |
|||
<button class="btn btn-close" @click="hideCreateMaintainModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr class="table-active"> |
|||
<th>單價</th> |
|||
<th>數量(月)</th> |
|||
<th>總價</th> |
|||
<th>備註</th> |
|||
</tr> |
|||
<tr> |
|||
<td><input type="number" class="form-control" x-model="modalMaintainInfo.price"></td> |
|||
<td><input type="number" class="form-control" x-model="modalMaintainInfo.num"></td> |
|||
<td><input type="text" disabled class="form-control" x-model="(modalMaintainInfo.price * modalMaintainInfo.num).toLocaleString()"></td> |
|||
<td><input type="text" class="form-control" x-model="modalMaintainInfo.memo"></td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideCreateMaintainModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="createMaintainOptionFn()">新增</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideCreateMaintainModal()"></div> |
|||
</div> |
@ -0,0 +1,36 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.maintainToElevator" x-ref="toMaintainOptionElevatorModal" id="toMaintainOptionElevatorModal"> |
|||
<div class="window-modal-content modal-m"> |
|||
<div class="window-modal-header"> |
|||
<h4>配對電梯</h4> |
|||
<button class="btn btn-close" @click="hideToMaintainOptionElevatorModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr> |
|||
<th>項次</th> |
|||
<th>規格</th> |
|||
<th>選擇</th> |
|||
</tr> |
|||
<template x-for="elevator in toElevators"> |
|||
<tr> |
|||
<td x-text="elevator.id"></td> |
|||
<td x-text="elevator.model"></td> |
|||
<td><input type="radio" name="maintainOptionToElevator" :value="elevator.id" class="form-check-input" x-model="toElevatorNo" /></td> |
|||
</tr> |
|||
</template> |
|||
<tr x-show="toElevators.length == 0"> |
|||
<td colspan="3"> |
|||
<small class="text-danger" style="font-size:13px;font-weight:600">暫無可選電梯,請先新增電梯規格!</small> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideToMaintainOptionElevatorModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="chkMaintainOptionToElevators()">確認</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideToMaintainOptionElevatorModal()"></div> |
|||
</div> |
@ -0,0 +1,59 @@ |
|||
<div class="window-modal " x-cloak data-type="window-modal" x-show="modalShow.option" x-ref="optionsModal" id="optionModal"> |
|||
<div class="window-modal-content modal-xl"> |
|||
<div class="window-modal-header"> |
|||
<h4>OPTION加價</h4> |
|||
<button class="btn btn-close" @click="hideOptionsModal()">X</button> |
|||
<div class="mt-3"> |
|||
<input type="text" class="form-control" x-model="searchtext" @keyup="searchOptions()" placeholder="搜尋..." /> |
|||
</div> |
|||
<div class="categories mt-3"> |
|||
<button :class="['btn', 'mt-2', (kind==1) ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions(1)">顯示全部</button> |
|||
<button :class="['btn', 'mt-2', (kind=='A') ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions('A', 1)">A-1 車廂意匠</button> |
|||
<button :class="['btn', 'mt-2', (kind=='B') ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions('B', 1)">A-2 車廂內裝</button> |
|||
<button :class="['btn', 'mt-2', (kind=='C') ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions('C', 1)">A-3 車廂外部</button> |
|||
<button :class="['btn', 'mt-2', (kind=='D') ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions('D', 1)">A-4 控制與其他</button> |
|||
<button :class="['btn', 'mt-2', (kind=='E') ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions('E', 1)">B-1 平台梯</button> |
|||
<button :class="['btn', 'mt-2', (kind=='F') ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions('F', 1)">C-1 汰改</button> |
|||
<br /><br /> |
|||
<template x-for="button in buttons"> |
|||
<button style="margin-right:3px" :class="['btn', (button.type == subkind) ? 'btn-primary' : 'btn-secondary text-light']" @click="searchOptions(null, button.type)" x-text="button.name"></button> |
|||
</template> |
|||
</div> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table " border=1> |
|||
<thead> |
|||
<tr> |
|||
<th>ID</th> |
|||
<th>名稱</th> |
|||
<th>規格</th> |
|||
<th>備註</th> |
|||
<th>配置</th> |
|||
<th>單位</th> |
|||
<th>定價</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<template x-for="(option, idx) in options" :key="option.id"> |
|||
<tr style="cursor:pointer;" :class="option.selected == 1 ? ' selected' : ''" x-show="option.isShow == 1" @click="selectOption(idx, option.id, option.group_name, option.price, option.memo)"> |
|||
<td x-text='option.id' name="optionID" class="bg-transparent"></td> |
|||
<td x-text="option.group_name" class="bg-transparent"> </td> |
|||
<td x-text="option.spec" class="bg-transparent"></td> |
|||
<td x-text="option.memo" class="bg-transparent"></td> |
|||
<td x-text="optionalArr[option.optional]" class="bg-transparent"></td> |
|||
<td x-text="option.unit" class="bg-transparent"></td> |
|||
<td x-text="option.price" class="bg-transparent"></td> |
|||
</tr> |
|||
</template> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @click="hideOptionsModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @click="chkOptions()">確認</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideOptionsModal()"></div> |
|||
</div> |
@ -0,0 +1,36 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.optionToElevator" x-ref="toElevatorModal" id="toElevatorModal"> |
|||
<div class="window-modal-content modal-m"> |
|||
<div class="window-modal-header"> |
|||
<h4>配對電梯</h4> |
|||
<button class="btn btn-close" @click="hideToElevatorModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr> |
|||
<th>項次</th> |
|||
<th>規格</th> |
|||
<th>選擇</th> |
|||
</tr> |
|||
<template x-for="elevator in toElevators"> |
|||
<tr> |
|||
<td x-text="elevator.id"></td> |
|||
<td x-text="elevator.model"></td> |
|||
<td><input type="radio" name="optionToElevator" :value="elevator.id" class="form-check-input" x-model="toElevatorNo" /></td> |
|||
</tr> |
|||
</template> |
|||
<tr x-show="toElevators.length == 0"> |
|||
<td colspan="3"> |
|||
<small class="text-danger" style="font-size:13px;font-weight:600">暫無可選電梯,請先新增電梯規格!</small> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideToElevatorModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="chkOptionToElevators()">確認</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideToElevatorModal()"></div> |
|||
</div> |
@ -0,0 +1,33 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.other" x-ref="createOtherOptionModal" id="createOtherOptionModal"> |
|||
<div class="window-modal-content modal-xl"> |
|||
<div class="window-modal-header"> |
|||
<h4>新增除外項目</h4> |
|||
<button class="btn btn-close" @click="hideCreateOtherOptionModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr class="table-active"> |
|||
<th>詢價單號</th> |
|||
<th>項目名稱</th> |
|||
<th>單價</th> |
|||
<th>數量</th> |
|||
<th>複價</th> |
|||
</tr> |
|||
<tr> |
|||
<td><input type="text" class="form-control" x-model="modalOtherOptionInfo.pr_no"></td> |
|||
<td><input type="text" class="form-control" x-model="modalOtherOptionInfo.name"></td> |
|||
<td><input type="number" class="form-control" x-model="modalOtherOptionInfo.price"></td> |
|||
<td><input type="number" class="form-control" x-model="modalOtherOptionInfo.num"></td> |
|||
<td><input type="text" disabled class="form-control" x-model="(modalOtherOptionInfo.price * modalOtherOptionInfo.num).toLocaleString()"></td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideCreateOtherOptionModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="createOtherOptionFn()">新增</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideCreateOtherOptionModal()"></div> |
|||
</div> |
@ -0,0 +1,36 @@ |
|||
<div class="window-modal" x-cloak data-type="window-modal" x-show="modalShow.otherToElevator" x-ref="toOtherOptionElevatorModal" id="toOtherOptionElevatorModal"> |
|||
<div class="window-modal-content modal-m"> |
|||
<div class="window-modal-header"> |
|||
<h4>配對電梯</h4> |
|||
<button class="btn btn-close" @click="hideToOtherOptionElevatorModal()">X</button> |
|||
</div> |
|||
<div class="window-modal-body"> |
|||
<div> |
|||
<table class="table"> |
|||
<tr> |
|||
<th>項次</th> |
|||
<th>規格</th> |
|||
<th>選擇</th> |
|||
</tr> |
|||
<template x-for="elevator in toElevators"> |
|||
<tr> |
|||
<td x-text="elevator.id"></td> |
|||
<td x-text="elevator.model"></td> |
|||
<td><input type="radio" name="otherOptionToElevator" :value="elevator.id" class="form-check-input" x-model="toElevatorNo" /></td> |
|||
</tr> |
|||
</template> |
|||
<tr x-show="toElevators.length == 0"> |
|||
<td colspan="3"> |
|||
<small class="text-danger" style="font-size:13px;font-weight:600">暫無可選電梯,請先新增電梯規格!</small> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<button type="button" class="btn btn-secondary" @click="hideToOtherOptionElevatorModal()">關閉</button> |
|||
<button type="button" class="btn btn-primary" @click="chkOtherOptionToElevators()">確認</button> |
|||
</div> |
|||
</div> |
|||
<div class="window-back" @click="hideToOtherOptionElevatorModal()"></div> |
|||
</div> |
@ -0,0 +1,49 @@ |
|||
<?php |
|||
$envFile = __DIR__ . '/.env'; // .env 文件的路径 |
|||
|
|||
if (file_exists($envFile)) { |
|||
$lines = file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); |
|||
if ($lines !== false) { |
|||
foreach ($lines as $line) { |
|||
list($key, $value) = explode('=', $line, 2); |
|||
$key = trim($key); |
|||
$value = trim($value); |
|||
// 设置环境变量 |
|||
putenv("$key=$value"); |
|||
} |
|||
} |
|||
} |
|||
$db_hostname = getenv('DB_HOST'); //資料庫主機名稱 |
|||
$db_username = getenv('DB_USERNAME'); //登入資料庫的管理者的帳號 |
|||
$db_password = getenv('DB_PASSWORD'); //登入密碼 |
|||
$db_name = getenv('DB_DATABASE'); //使用的資料庫 |
|||
$db_charset = 'utf8'; //設定字元編碼 |
|||
|
|||
|
|||
$db_hostname = 'localhost'; //資料庫主機名稱 |
|||
$db_username = 'root'; //登入資料庫的管理者的帳號 |
|||
$db_password = ''; //登入密碼 |
|||
$db_name = 'appwms'; //使用的資料庫 |
|||
$db_charset = 'utf8'; //設定字元編碼 |
|||
//建立PDO的指定工作 |
|||
$dsn = "mysql:host=$db_hostname;dbname=$db_name;charset=$db_charset"; |
|||
|
|||
try{ |
|||
//使用PDO連接到MySQL資料庫,建立PDO物件 |
|||
$conn = new PDO($dsn, $db_username, $db_password); |
|||
|
|||
//當錯誤發生時會將錯誤資訊放到一個類物件裡(PDOException) |
|||
//PDO異常處理,PDO::ATTR_ERRMODE,有以下三種值的設定 |
|||
//PDO::ERRMODE_SILENT: 預設模式,不主動報錯,需要以$conn->errorInfo()的形式獲取錯誤資訊 |
|||
//PDO::ERRMODE_WARNING: 引發 E_WARNING 錯誤,主動報錯 |
|||
//PDO::ERRMODE_EXCEPTION: 主動抛出 exceptions 異常,需要以try{}cath(){}輸出錯誤資訊。 |
|||
//設定主動以警告的形式報錯 |
|||
$conn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); |
|||
//如果連接錯誤,將抛出一個PDOException異常對象 |
|||
} |
|||
catch ( PDOException $e ){ |
|||
//如果連結資料庫失敗則顯示錯誤訊並停止本頁的工作 |
|||
die("ERROR!!!: ". $e->getMessage()); |
|||
} |
|||
|
|||
//$conn = null; //關閉資料庫的連線 |
Loading…
Reference in new issue