| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- # -*- coding: utf-8 -*-
- """Patch waybill index.vue and WaybillDetail.vue for attachment and list columns."""
- import os
- import re
- ROOT = os.path.dirname(os.path.dirname(__file__))
- INDEX = os.path.join(ROOT, "ruoyi-ui", "src", "views", "basic", "waybill", "index.vue")
- DETAIL = os.path.join(ROOT, "ruoyi-ui", "src", "views", "basic", "waybill", "components", "WaybillDetail.vue")
- TABLE_OLD = r''' <el-table border stripe v-loading="loading" :data="waybillList" @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="\u8fd0\u5355\u53f7" prop="waybillNo" min-width="150" align="center" show-overflow-tooltip />
- <el-table-column label="\u8fd0\u8f93\u7c7b\u578b" prop="transportType" width="110" align="center" />
- <el-table-column label="\u5355\u636e\u65e5\u671f" prop="documentDate" width="110" align="center" />
- <el-table-column label="\u53d1\u8d27\u4f01\u4e1a" prop="senderCompany" min-width="140" align="center" show-overflow-tooltip />
- <el-table-column label="\u6536\u8d27\u4f01\u4e1a" prop="receiverCompany" min-width="140" align="center" show-overflow-tooltip />
- <el-table-column label="\u9884\u8ba1\u53d1\u8f66" prop="planDepartTime" width="160" align="center" />
- <el-table-column label="\u9884\u8ba1\u5230\u8fbe" prop="planArriveTime" width="160" align="center" />
- <el-table-column label="\u603b\u6570\u91cf" prop="totalQuantity" width="90" align="right" />
- <el-table-column label="\u603b\u91cd\u91cf(kg)" prop="totalWeight" width="100" align="right" />
- <el-table-column label="\u5ba1\u6838\u72b6\u6001" prop="auditStatus" width="100" align="center">
- <template slot-scope="scope">
- <el-tag :type="auditTagType(scope.row.auditStatus)" size="small">{{ auditStatusLabel(scope.row.auditStatus) }}</el-tag>
- </template>
- </el-table-column>'''
- TABLE_NEW = r''' <el-table border stripe v-loading="loading" :data="waybillList" @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column label="\u8fd0\u5355\u7f16\u53f7" prop="waybillNo" min-width="140" align="center" show-overflow-tooltip />
- <el-table-column label="\u53d1\u8fd0\u65e5\u671f" prop="documentDate" width="110" align="center" />
- <el-table-column label="\u6536\u8d27\u5ba2\u6237" prop="receiverCompany" min-width="130" align="center" show-overflow-tooltip />
- <el-table-column label="\u8d77\u6b62\u5730\u70b9" min-width="160" align="center" show-overflow-tooltip>
- <template slot-scope="scope">{{ formatRoute(scope.row) }}</template>
- </el-table-column>
- <el-table-column label="\u8f66\u724c" prop="carNum" width="100" align="center" />
- <el-table-column label="\u53f8\u673a" prop="driverName" width="90" align="center" />
- <el-table-column label="\u5f53\u524d\u6e29\u5ea6" width="100" align="center">
- <template slot-scope="scope">
- <span :class="{ 'text-danger': isTempOverLimit(scope.row) }">{{ displayCurrentTemp(scope.row) }}</span>
- </template>
- </el-table-column>
- <el-table-column label="\u72b6\u6001" width="90" align="center">
- <template slot-scope="scope">
- <el-tag :type="transportStatusTag(scope.row)" size="small">{{ transportStatusText(scope.row) }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="\u5230\u8fbe\u65f6\u95f4" prop="planArriveTime" width="160" align="center" />'''
- FORM_INSERT = r'''
- <el-divider content-position="left">\u8fd0\u5355\u9644\u4ef6</el-divider>
- <el-row :gutter="12">
- <el-col :span="24">
- <el-form-item label="\u8fd0\u5355\u6587\u4ef6">
- <file-upload v-model="form.attachment" :limit="10" :file-size="20" />
- </el-form-item>
- </el-col>
- </el-row>
- '''
- METHODS_INSERT = r'''
- formatRoute(row) {
- const from = row.senderCity || row.senderDistrict || row.senderProvince || "";
- const to = row.receiverCity || row.receiverDistrict || row.receiverProvince || "";
- return from && to ? from + " \u2192 " + to : "-";
- },
- transportStatusText(row) {
- const audit = row.auditStatus;
- const now = Date.now();
- const depart = row.planDepartTime ? new Date(row.planDepartTime).getTime() : null;
- const arrive = row.planArriveTime ? new Date(row.planArriveTime).getTime() : null;
- if (audit === 0) return "\u8349\u7a3f";
- if (audit === 1) return "\u5f85\u5ba1\u6838";
- if (depart && now < depart) return "\u5df2\u786e\u8ba4";
- if (arrive && now < arrive) return "\u5728\u9014";
- if (arrive && now >= arrive) return "\u5df2\u5230\u8fbe";
- return "\u5df2\u901a\u8fc7";
- },
- transportStatusTag(row) {
- const text = this.transportStatusText(row);
- const map = { "\u8349\u7a3f": "info", "\u5f85\u5ba1\u6838": "warning", "\u5df2\u786e\u8ba4": "success", "\u5728\u9014": "success", "\u5df2\u5230\u8fbe": "success", "\u5df2\u901a\u8fc7": "success" };
- return map[text] || "info";
- },
- displayCurrentTemp(row) {
- if (row.currentTemp != null && row.currentTemp !== "") {
- return Number(row.currentTemp).toFixed(1) + "\u00b0C";
- }
- const max = row.tempMax != null ? Number(row.tempMax) : null;
- const min = row.tempMin != null ? Number(row.tempMin) : 0;
- const audit = row.auditStatus;
- const now = Date.now();
- const depart = row.planDepartTime ? new Date(row.planDepartTime).getTime() : null;
- const arrive = row.planArriveTime ? new Date(row.planArriveTime).getTime() : null;
- const inTransit = audit === 2 && depart && now > depart && arrive && now < arrive;
- let ratio = depart && arrive ? (now - depart) / (arrive - depart) : 0.5;
- ratio = Math.max(0, Math.min(1, ratio || 0.5));
- const temp = inTransit && ratio > 0.4 && max != null ? max + 2.2 : (min + (max || 6)) / 2;
- return Number(temp).toFixed(1) + "\u00b0C";
- },
- isTempOverLimit(row) {
- const max = row.tempMax != null ? Number(row.tempMax) : null;
- const min = row.tempMin != null ? Number(row.tempMin) : null;
- const cur = parseFloat(this.displayCurrentTemp(row));
- if (isNaN(cur)) return false;
- return (max != null && cur > max) || (min != null && cur < min);
- },
- '''
- DETAIL_ATTACHMENTS = r''' attachments() {
- const raw = this.detail.attachment;
- const base = this.formatDateTime(this.detail.createTime) || "";
- const baseUrl = process.env.VUE_APP_BASE_API || "";
- if (!raw) return [];
- return String(raw).split(",").filter(Boolean).map((url) => {
- const path = url.trim();
- const name = path.lastIndexOf("/") >= 0 ? path.substring(path.lastIndexOf("/") + 1) : path;
- return { name, url: path, fullUrl: path.startsWith("http") ? path : baseUrl + path, time: base };
- });
- },'''
- DETAIL_PREVIEW = r''' previewFile(file) {
- const url = file.fullUrl || file.url;
- if (url) window.open(url, "_blank");
- else this.$modal.msgInfo("\u9884\u89c8\uff1a" + file.name);
- },
- downloadFile(file) {
- const url = file.fullUrl || file.url;
- if (url) window.open(url, "_blank");
- else this.$modal.msgInfo("\u4e0b\u8f7d\uff1a" + file.name);
- }'''
- def patch_index():
- text = open(INDEX, encoding="utf-8").read()
- # table: replace between selection and ???? column
- m = re.search(
- r'<el-table border stripe.*?<el-table-column label="\u64cd\u4f5c"',
- text,
- re.DOTALL,
- )
- if not m:
- start = text.find('<el-table border stripe')
- end = text.find('class-name="small-padding fixed-width"')
- if start < 0 or end < 0:
- raise SystemExit("table block not found")
- end = text.rfind("<el-table-column", 0, end)
- text = text[:start] + TABLE_NEW.encode("utf-8").decode("unicode_escape") + "\n " + text[end:]
- else:
- block = m.group(0)
- new_block = TABLE_NEW.encode("utf-8").decode("unicode_escape") + "\n <el-table-column label=\"\u64cd\u4f5c\""
- text = text.replace(block, new_block, 1)
- if "file-upload" not in text:
- text = text.replace(
- 'import WaybillDetail from "./components/WaybillDetail";',
- 'import WaybillDetail from "./components/WaybillDetail";\nimport FileUpload from "@/components/FileUpload";',
- )
- text = text.replace(
- "components: { WaybillDetail },",
- "components: { WaybillDetail, FileUpload },",
- )
- if "\u8fd0\u5355\u9644\u4ef6" not in text:
- marker = " </el-row>\n </el-form>\n\n <div slot=\"footer\" class=\"dialog-footer\">"
- alt = " </el-row>\n </el-form>"
- insert = FORM_INSERT.encode("utf-8").decode("unicode_escape")
- if marker in text:
- text = text.replace(marker, insert + marker, 1)
- else:
- idx = text.rfind('label="\u9884\u4f30\u91cc\u7a0b')
- if idx < 0:
- idx = text.rfind("estimateDistance")
- end = text.find("</el-row>", idx)
- text = text[: end + len("</el-row>")] + insert + text[end + len("</el-row>") :]
- if "formatRoute(row)" not in text:
- text = text.replace(
- " canEdit(row) {",
- METHODS_INSERT.encode("utf-8").decode("unicode_escape") + " canEdit(row) {",
- 1,
- )
- if 'attachment: ""' not in text and "attachment:" not in text.split("reset()")[1][:800]:
- text = text.replace(
- 'remark: "",',
- 'remark: "",\n attachment: "",',
- 1,
- )
- text = text.replace(
- "planSignTime: undefined,",
- "planSignTime: undefined,\n currentTemp: undefined,",
- 1,
- )
- open(INDEX, "w", encoding="utf-8", newline="\n").write(text)
- print("patched index.vue")
- def patch_detail():
- text = open(DETAIL, encoding="utf-8").read()
- # replace attachments computed
- pat = r"attachments\(\) \{[\s\S]*?\n \},\n watch:"
- rep = DETAIL_ATTACHMENTS.encode("utf-8").decode("unicode_escape") + " watch:"
- if re.search(pat, text):
- text = re.sub(pat, rep, text, count=1)
- # replace preview/download
- pat2 = r"previewFile\(file\) \{[\s\S]*?downloadFile\(file\) \{[\s\S]*?\n \}\n \}\n\};"
- rep2 = DETAIL_PREVIEW.encode("utf-8").decode("unicode_escape") + "\n }\n};"
- if re.search(pat2, text):
- text = re.sub(pat2, rep2, text, count=1)
- open(DETAIL, "w", encoding="utf-8", newline="\n").write(text)
- print("patched WaybillDetail.vue")
- if __name__ == "__main__":
- patch_index()
- patch_detail()
|