index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. <template>
  2. <div class="tenant">
  3. <div class="content">
  4. <byTable
  5. :source="sourceList.data"
  6. :pagination="sourceList.pagination"
  7. :config="config"
  8. :loading="loading"
  9. :selectConfig="selectConfig"
  10. highlight-current-row
  11. :action-list="[
  12. {
  13. text: '新建销售合同',
  14. action: () => newContract(),
  15. },
  16. ]"
  17. @get-list="getList"
  18. >
  19. <template #code="{ item }">
  20. <div style="width: 100%">
  21. <a
  22. style="color: #409eff; cursor: pointer; word-break: break-all"
  23. @click="openDetails(item)"
  24. >{{ item.code }}</a
  25. >
  26. </div>
  27. </template>
  28. <template #amount="{ item }">
  29. <div>
  30. <span style="padding-right: 4px">{{ item.currency }}</span>
  31. <span>{{ moneyFormat(item.amount, 2) }}</span>
  32. </div>
  33. </template>
  34. <template #buyCorporationName="{ item }">
  35. <div style="width: 100%">
  36. <a
  37. style="color: #409eff; cursor: pointer"
  38. @click="clickCorporationName(item)"
  39. >{{ item.buyCorporationName }}</a
  40. >
  41. </div>
  42. </template>
  43. <template #tags="{ item }">
  44. <div style="width: 100%">
  45. <el-tag
  46. style="margin-right: 8px"
  47. type="success"
  48. v-for="(tag, index) in item.tags"
  49. closable
  50. :key="index"
  51. @close="tagClose(tag, item)"
  52. >
  53. {{ dictValueLabel(tag, customerTag) }}
  54. </el-tag>
  55. <template v-if="item.tags.length !== customerTag.length">
  56. <el-select
  57. v-if="item.addTagShow"
  58. v-model="addTag"
  59. style="width: 100%"
  60. @change="
  61. (val) => {
  62. return changeTag(val, item);
  63. }
  64. "
  65. >
  66. <el-option
  67. v-for="tag in customerTag"
  68. :key="tag.value"
  69. :label="tag.label"
  70. :value="tag.value"
  71. :disabled="judgeTagSelect(item.tags, tag.value)"
  72. />
  73. </el-select>
  74. <el-tag
  75. style="cursor: pointer"
  76. type="success"
  77. @click="showSelect(item)"
  78. v-else
  79. >
  80. +
  81. </el-tag>
  82. </template>
  83. </div>
  84. </template>
  85. <template #advanceRatio="{ item }">
  86. <div>
  87. <span>{{ moneyFormat(item.advanceRatio, 2) }}%</span>
  88. </div>
  89. </template>
  90. <template #scale="{ item }">
  91. <div>
  92. {{ computeScale(item) }}
  93. </div>
  94. </template>
  95. </byTable>
  96. </div>
  97. <el-dialog title="打印" v-if="openPrint" v-model="openPrint" width="920">
  98. <ContractPDFOne :rowData="rowData"></ContractPDFOne>
  99. <template #footer>
  100. <el-button @click="openPrint = false" size="large">取消</el-button>
  101. <el-button type="primary" v-print="printObj" size="large"
  102. >打印</el-button
  103. >
  104. <el-button type="primary" @click="clickDownload()" size="large"
  105. >下载PDF</el-button
  106. >
  107. </template>
  108. </el-dialog>
  109. <el-dialog
  110. title="交接单"
  111. v-if="openHandoverSlip"
  112. v-model="openHandoverSlip"
  113. width="600"
  114. >
  115. <byForm
  116. :formConfig="formConfig"
  117. :formOption="formOption"
  118. v-model="handoverSlipForm"
  119. >
  120. <template #file>
  121. <div style="width: 100%">
  122. <el-upload
  123. v-model:fileList="handoverSlipForm.fileList"
  124. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  125. :data="uploadData"
  126. multiple
  127. :before-upload="uploadFile"
  128. :on-success="handleSuccess"
  129. :on-preview="onPreviewFile"
  130. >
  131. <el-button type="primary" plain>选择</el-button>
  132. </el-upload>
  133. </div>
  134. </template>
  135. <template #indication>
  136. <div style="width: 100%">
  137. <el-upload
  138. v-model:fileList="handoverSlipForm.packageFileList"
  139. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  140. :data="indicationUploadData"
  141. multiple
  142. :before-upload="indicationUploadFile"
  143. :on-success="handleSuccess"
  144. :on-preview="onPreviewFile"
  145. >
  146. <el-button type="primary" plain>选择</el-button>
  147. </el-upload>
  148. </div>
  149. </template>
  150. </byForm>
  151. <template #footer>
  152. <el-button @click="openHandoverSlip = false" size="large"
  153. >关 闭</el-button
  154. >
  155. <el-button type="primary" @click="submitHandoverSlip()" size="large"
  156. >确 定</el-button
  157. >
  158. </template>
  159. </el-dialog>
  160. <el-dialog
  161. title="合同详情"
  162. v-if="openDetailsDialog"
  163. v-model="openDetailsDialog"
  164. width="1100"
  165. >
  166. <ContractDetails :contractId="currentContractId"></ContractDetails>
  167. </el-dialog>
  168. </div>
  169. </template>
  170. <script setup>
  171. import { computed, ref } from "vue";
  172. import byTable from "@/components/byTable/index";
  173. import byForm from "@/components/byForm/index";
  174. import useUserStore from "@/store/modules/user";
  175. import { ElMessage, ElMessageBox } from "element-plus";
  176. import ContractDetails from "@/components/contractCom/contractDetails.vue";
  177. import ContractPDFOne from "@/components/PDF/contractPDFOne.vue";
  178. const route = useRoute();
  179. const { proxy } = getCurrentInstance();
  180. const accountCurrency = ref([]);
  181. const tradeMethods = ref([]);
  182. const corporationList = ref([]);
  183. const customerList = ref([]);
  184. const userList = ref([]);
  185. const shippingMethod = ref([]);
  186. const customerTag = ref([]);
  187. const openDetailsDialog = ref(false);
  188. const status = ref([
  189. {
  190. label: "草稿",
  191. value: 0,
  192. },
  193. {
  194. label: "审批中",
  195. value: 10,
  196. },
  197. {
  198. label: "驳回",
  199. value: 20,
  200. },
  201. {
  202. label: "审批通过",
  203. value: 30,
  204. },
  205. {
  206. label: "变更中",
  207. value: 60,
  208. },
  209. {
  210. label: "已变更",
  211. value: 70,
  212. },
  213. {
  214. label: "作废",
  215. value: 88,
  216. },
  217. {
  218. label: "终止",
  219. value: 99,
  220. },
  221. ]);
  222. const sourceList = ref({
  223. data: [],
  224. pagination: {
  225. total: 0,
  226. pageNum: 1,
  227. pageSize: 10,
  228. keyword: "",
  229. status: "",
  230. sellCorporationId: "",
  231. },
  232. });
  233. const loading = ref(false);
  234. const selectConfig = computed(() => {
  235. return [
  236. {
  237. label: "审批状态",
  238. prop: "status",
  239. data: status.value,
  240. },
  241. {
  242. label: "归属公司",
  243. prop: "sellCorporationId",
  244. data: corporationList.value,
  245. },
  246. ];
  247. });
  248. const config = computed(() => {
  249. return [
  250. {
  251. attrs: {
  252. label: "合同号",
  253. slot: "code",
  254. width: 140,
  255. },
  256. },
  257. {
  258. attrs: {
  259. label: "归属公司",
  260. prop: "sellCorporationId",
  261. "min-width": 220,
  262. },
  263. render(type) {
  264. return proxy.dictValueLabel(type, corporationList.value);
  265. },
  266. },
  267. {
  268. attrs: {
  269. label: "业务员",
  270. prop: "createUser",
  271. width: 100,
  272. },
  273. render(type) {
  274. return proxy.dictValueLabel(type, userList.value);
  275. },
  276. },
  277. {
  278. attrs: {
  279. label: "下单时间",
  280. prop: "createTime",
  281. width: 160,
  282. },
  283. },
  284. {
  285. attrs: {
  286. label: "客户名称",
  287. slot: "buyCorporationName",
  288. "min-width": 140,
  289. },
  290. },
  291. {
  292. attrs: {
  293. label: "客户标签",
  294. slot: "tags",
  295. width: 180,
  296. },
  297. },
  298. {
  299. attrs: {
  300. label: "预付比例",
  301. slot: "advanceRatio",
  302. width: 100,
  303. align: "right",
  304. },
  305. },
  306. {
  307. attrs: {
  308. label: "合同金额",
  309. slot: "amount",
  310. width: 140,
  311. align: "right",
  312. },
  313. },
  314. {
  315. attrs: {
  316. label: "汇率",
  317. prop: "rate",
  318. width: 80,
  319. align: "right",
  320. },
  321. render(rate) {
  322. return proxy.moneyFormat(rate, 4);
  323. },
  324. },
  325. {
  326. attrs: {
  327. label: "合同金额(CNY)",
  328. prop: "amountCNY",
  329. width: 160,
  330. align: "right",
  331. },
  332. render(amountCNY) {
  333. return proxy.moneyFormat(amountCNY, 2);
  334. },
  335. },
  336. {
  337. attrs: {
  338. label: "到账金额(CNY)",
  339. prop: "sumClaimMoney",
  340. width: 160,
  341. align: "right",
  342. },
  343. render(sumClaimMoney) {
  344. return proxy.moneyFormat(sumClaimMoney, 2);
  345. },
  346. },
  347. {
  348. attrs: {
  349. label: "到账比例",
  350. slot: "scale",
  351. width: 100,
  352. align: "right",
  353. },
  354. },
  355. {
  356. attrs: {
  357. label: "审批状态",
  358. prop: "status",
  359. width: 140,
  360. },
  361. render(type) {
  362. return proxy.dictValueLabel(type, status.value);
  363. },
  364. },
  365. {
  366. attrs: {
  367. label: "操作",
  368. width: 160,
  369. align: "center",
  370. fixed: "right",
  371. },
  372. renderHTML(row) {
  373. return [
  374. {
  375. attrs: {
  376. label: "交接单",
  377. type: "primary",
  378. text: true,
  379. },
  380. el: "button",
  381. click() {
  382. clickHandoverSlip(row);
  383. },
  384. },
  385. row.status == 30
  386. ? {
  387. attrs: {
  388. label: "变更",
  389. type: "primary",
  390. text: true,
  391. },
  392. el: "button",
  393. click() {
  394. clickAlteration(row);
  395. },
  396. }
  397. : {},
  398. {
  399. attrs: {
  400. label: "打印",
  401. type: "primary",
  402. text: true,
  403. },
  404. el: "button",
  405. click() {
  406. clickPrint(row);
  407. },
  408. },
  409. {
  410. attrs: {
  411. label: "作废",
  412. type: "primary",
  413. text: true,
  414. },
  415. el: "button",
  416. click() {
  417. ElMessageBox.confirm(
  418. "此操作将永久删除该数据, 是否继续?",
  419. "提示",
  420. {
  421. confirmButtonText: "确定",
  422. cancelButtonText: "取消",
  423. type: "warning",
  424. }
  425. ).then(() => {
  426. proxy
  427. .post("/contract/edit", {
  428. id: row.id,
  429. status: 88,
  430. })
  431. .then(() => {
  432. ElMessage({
  433. message: "作废成功",
  434. type: "success",
  435. });
  436. getList();
  437. });
  438. });
  439. },
  440. },
  441. ];
  442. },
  443. },
  444. ];
  445. });
  446. const getDict = () => {
  447. proxy
  448. .getDictOne([
  449. "customer_tag",
  450. "trade_mode",
  451. "account_currency",
  452. "shipping_method",
  453. ])
  454. .then((res) => {
  455. customerTag.value = res["customer_tag"].map((x) => ({
  456. label: x.dictValue,
  457. value: x.dictKey,
  458. }));
  459. tradeMethods.value = res["trade_mode"].map((x) => ({
  460. label: x.dictValue,
  461. value: x.dictKey,
  462. }));
  463. accountCurrency.value = res["account_currency"].map((x) => ({
  464. label: x.dictValue,
  465. value: x.dictKey,
  466. }));
  467. shippingMethod.value = res["shipping_method"].map((x) => ({
  468. label: x.dictValue,
  469. value: x.dictKey,
  470. }));
  471. });
  472. proxy.post("/corporation/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  473. corporationList.value = res.rows.map((item) => {
  474. return {
  475. ...item,
  476. label: item.name,
  477. value: item.id,
  478. };
  479. });
  480. });
  481. proxy.post("/customer/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  482. customerList.value = res.rows.map((item) => {
  483. return {
  484. ...item,
  485. label: item.name,
  486. value: item.id,
  487. };
  488. });
  489. });
  490. proxy
  491. .get("/tenantUser/list", {
  492. pageNum: 1,
  493. pageSize: 10000,
  494. tenantId: useUserStore().user.tenantId,
  495. })
  496. .then((res) => {
  497. userList.value = res.rows.map((item) => {
  498. return {
  499. label: item.nickName,
  500. value: item.userId,
  501. };
  502. });
  503. });
  504. };
  505. const getList = async (req) => {
  506. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  507. loading.value = true;
  508. proxy.post("/contract/page", sourceList.value.pagination).then((res) => {
  509. res.rows.forEach((x) => {
  510. x.addTagShow = false;
  511. if (x.tag) {
  512. x.tags = x.tag.split(",");
  513. } else {
  514. x.tags = [];
  515. }
  516. });
  517. sourceList.value.data = res.rows;
  518. sourceList.value.pagination.total = res.total;
  519. setTimeout(() => {
  520. loading.value = false;
  521. }, 200);
  522. });
  523. };
  524. getDict();
  525. if (route.query.code) {
  526. sourceList.value.pagination.keyword = route.query.code;
  527. }
  528. getList();
  529. const newContract = () => {
  530. proxy.$router.replace({
  531. path: "/platform_manage/process/processApproval",
  532. query: {
  533. flowKey: "contract_flow",
  534. flowName: "销售合同审批流程",
  535. random: proxy.random(),
  536. tenantType: "EHSD",
  537. },
  538. });
  539. };
  540. const openPrint = ref(false);
  541. const rowData = ref({});
  542. const clickPrint = (row) => {
  543. rowData.value = {
  544. id: row.id,
  545. };
  546. openPrint.value = true;
  547. };
  548. const clickDownload = () => {
  549. proxy.getPdf("外销合同PDF文件");
  550. };
  551. const openHandoverSlip = ref(false);
  552. const handoverSlipForm = ref({
  553. id: "",
  554. code: "",
  555. buyCorporationName: "",
  556. fileList: [],
  557. packageFileList: [],
  558. });
  559. const formOption = reactive({
  560. inline: true,
  561. labelWidth: 100,
  562. itemWidth: 100,
  563. rules: [],
  564. });
  565. const formConfig = computed(() => {
  566. return [
  567. {
  568. type: "input",
  569. prop: "code",
  570. label: "合同编号",
  571. itemType: "text",
  572. disabled: true,
  573. },
  574. {
  575. type: "input",
  576. prop: "buyCorporationName",
  577. label: "客户名称",
  578. itemType: "text",
  579. disabled: true,
  580. },
  581. {
  582. type: "slot",
  583. slotName: "file",
  584. label: "交接单",
  585. },
  586. {
  587. type: "slot",
  588. slotName: "indication",
  589. label: "包装指示",
  590. },
  591. ];
  592. });
  593. const uploadData = ref({});
  594. const indicationUploadData = ref({});
  595. const clickHandoverSlip = (item) => {
  596. handoverSlipForm.value.id = item.id;
  597. handoverSlipForm.value.code = item.code;
  598. handoverSlipForm.value.buyCorporationName = item.buyCorporationName;
  599. if (item.fileInfoVos && item.fileInfoVos.length > 0) {
  600. handoverSlipForm.value.fileList = item.fileInfoVos.map((item) => {
  601. return {
  602. raw: item,
  603. name: item.fileName,
  604. url: item.fileUrl,
  605. };
  606. });
  607. } else {
  608. handoverSlipForm.value.fileList = [];
  609. }
  610. if (item.packageFileInfoVOList && item.packageFileInfoVOList.length > 0) {
  611. handoverSlipForm.value.packageFileList = item.packageFileInfoVOList.map(
  612. (item) => {
  613. return {
  614. raw: item,
  615. name: item.fileName,
  616. url: item.fileUrl,
  617. };
  618. }
  619. );
  620. } else {
  621. handoverSlipForm.value.packageFileList = [];
  622. }
  623. openHandoverSlip.value = true;
  624. };
  625. const uploadFile = async (file) => {
  626. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  627. uploadData.value = res.uploadBody;
  628. file.id = res.id;
  629. file.fileName = res.fileName;
  630. file.fileUrl = res.fileUrl;
  631. file.uploadState = true;
  632. return true;
  633. };
  634. const indicationUploadFile = async (file) => {
  635. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  636. indicationUploadData.value = res.uploadBody;
  637. file.id = res.id;
  638. file.fileName = res.fileName;
  639. file.fileUrl = res.fileUrl;
  640. file.uploadState = true;
  641. return true;
  642. };
  643. const handleSuccess = (any, UploadFile) => {
  644. UploadFile.raw.uploadState = false;
  645. };
  646. const onPreviewFile = (file) => {
  647. window.open(file.raw.fileUrl, "_blank");
  648. };
  649. const submitHandoverSlip = () => {
  650. if (
  651. handoverSlipForm.value.fileList &&
  652. handoverSlipForm.value.fileList.length > 0
  653. ) {
  654. for (let i = 0; i < handoverSlipForm.value.fileList.length; i++) {
  655. if (handoverSlipForm.value.fileList[i].raw.uploadState) {
  656. return ElMessage("文件上传中,请稍后提交");
  657. }
  658. }
  659. }
  660. if (
  661. handoverSlipForm.value.packageFileList &&
  662. handoverSlipForm.value.packageFileList.length > 0
  663. ) {
  664. for (let i = 0; i < handoverSlipForm.value.packageFileList.length; i++) {
  665. if (handoverSlipForm.value.packageFileList[i].raw.uploadState) {
  666. return ElMessage("文件上传中,请稍后提交");
  667. }
  668. }
  669. }
  670. let data = proxy.deepClone(handoverSlipForm.value);
  671. if (data.fileList && data.fileList.length > 0) {
  672. data.fileList = data.fileList.map((item) => {
  673. return {
  674. id: item.raw.id,
  675. fileName: item.raw.fileName,
  676. fileUrl: item.raw.fileUrl,
  677. };
  678. });
  679. } else {
  680. data.fileList = [];
  681. }
  682. if (data.packageFileList && data.packageFileList.length > 0) {
  683. data.packageFileList = data.packageFileList.map((item) => {
  684. return {
  685. id: item.raw.id,
  686. fileName: item.raw.fileName,
  687. fileUrl: item.raw.fileUrl,
  688. };
  689. });
  690. } else {
  691. data.packageFileList = [];
  692. }
  693. proxy.post("/contract/contractHandover", data).then(() => {
  694. ElMessage({
  695. message: "操作成功!",
  696. type: "success",
  697. });
  698. openHandoverSlip.value = false;
  699. getList();
  700. });
  701. };
  702. const addTag = ref("");
  703. const judgeTagSelect = (data, val) => {
  704. if (data && data.length > 0) {
  705. if (data.includes(val)) {
  706. return true;
  707. }
  708. }
  709. return false;
  710. };
  711. const changeTag = (val, item) => {
  712. let data = {
  713. id: item.buyCorporationId,
  714. tag: proxy.deepClone(item.tags),
  715. };
  716. data.tag.push(val);
  717. data.tag = data.tag.join(",");
  718. proxy.post("/customer/editTag", data).then(() => {
  719. ElMessage({
  720. message: "添加成功",
  721. type: "success",
  722. });
  723. item.addTagShow = false;
  724. addTag.value = "";
  725. getList();
  726. });
  727. };
  728. const tagClose = (val, item) => {
  729. let data = {
  730. id: item.buyCorporationId,
  731. tag: proxy.deepClone(item.tags),
  732. };
  733. data.tag = data.tag.filter((row) => row !== val);
  734. if (data.tag && data.tag.length > 0) {
  735. data.tag = data.tag.join(",");
  736. } else {
  737. data.tag = "";
  738. }
  739. proxy.post("/customer/editTag", data).then(() => {
  740. ElMessage({
  741. message: "删除成功",
  742. type: "success",
  743. });
  744. item.addTagShow = false;
  745. addTag.value = "";
  746. getList();
  747. });
  748. };
  749. const showSelect = (item) => {
  750. item.addTagShow = true;
  751. };
  752. const currentContractId = ref("");
  753. const openDetails = (row) => {
  754. currentContractId.value = row.id;
  755. openDetailsDialog.value = true;
  756. };
  757. const computeScale = (item) => {
  758. let text = 0;
  759. if (
  760. item.sumClaimMoney &&
  761. Number(item.sumClaimMoney) > 0 &&
  762. item.amountCNY &&
  763. Number(item.amountCNY) > 0
  764. ) {
  765. text = parseFloat(
  766. (Number(item.sumClaimMoney) / Number(item.amountCNY)) * 100
  767. ).toFixed(2);
  768. }
  769. return text + "%";
  770. };
  771. const clickCorporationName = (row) => {
  772. proxy.$router.push({
  773. name: "Portrait",
  774. query: {
  775. id: row.buyCorporationId,
  776. },
  777. });
  778. };
  779. const printObj = ref({
  780. id: "pdfDom",
  781. popTitle: "",
  782. extraCss:
  783. "https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css",
  784. extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
  785. });
  786. const clickAlteration = (row) => {
  787. proxy.$router.push({
  788. path: "/platform_manage/process/processApproval",
  789. query: {
  790. flowKey: "contract_update_flow",
  791. flowName: "销售合同变更流程",
  792. random: proxy.random(),
  793. businessId: row.id,
  794. },
  795. });
  796. };
  797. </script>
  798. <style lang="scss" scoped>
  799. .tenant {
  800. padding: 20px;
  801. }
  802. ::v-deep(.el-input-number .el-input__inner) {
  803. text-align: left;
  804. }
  805. .baseRow {
  806. min-height: 24px;
  807. border-top: 1px solid black;
  808. border-left: 1px solid black;
  809. }
  810. .contentRow {
  811. border-right: 1px solid black;
  812. line-height: 24px;
  813. padding-left: 4px;
  814. }
  815. </style>