index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. <template>
  2. <div class="user">
  3. <div class="tree">
  4. <treeList
  5. title="产品分类"
  6. submitType="1"
  7. :data="treeListData"
  8. v-model="sourceList.pagination.productClassifyId"
  9. @change="treeChange"
  10. @changeTreeList="getTreeList"
  11. >
  12. </treeList>
  13. </div>
  14. <div class="content">
  15. <byTable
  16. :source="sourceList.data"
  17. :pagination="sourceList.pagination"
  18. :config="config"
  19. :loading="loading"
  20. highlight-current-row
  21. :selectConfig="selectConfig"
  22. :table-events="{
  23. //element talbe事件都能传
  24. select: select,
  25. }"
  26. :action-list="[
  27. props.selectStatus
  28. ? {}
  29. : {
  30. text: 'Excel导入',
  31. action: () => openExcel(),
  32. disabled: false,
  33. },
  34. props.selectStatus
  35. ? {}
  36. : {
  37. text: '添加',
  38. action: () => openModal('add'),
  39. disabled: false,
  40. },
  41. ]"
  42. @get-list="getList"
  43. >
  44. <template #pic="{ item }">
  45. <div v-if="item.fileList.length > 0">
  46. <img
  47. :src="item.fileList[0].fileUrl"
  48. class="pic"
  49. @click="handleClickFile(item.fileList[0])"
  50. />
  51. </div>
  52. <div v-else></div>
  53. </template>
  54. <template #size="{ item }">
  55. <div>
  56. <span>{{ item.productLong }}cm</span>*
  57. <span>{{ item.productWide }}cm</span>*
  58. <span>{{ item.productHigh }}cm</span>
  59. </div>
  60. </template>
  61. <template #price="{ item }">
  62. <div>
  63. <span v-if="item.price">{{ item.currency }} {{ item.price }}</span>
  64. </div>
  65. </template>
  66. <template #costPrice="{ item }">
  67. <div>
  68. <span v-if="item.costPrice"
  69. >{{ item.costCurrency }} {{ item.costPrice }}</span
  70. >
  71. </div>
  72. </template>
  73. </byTable>
  74. </div>
  75. <el-dialog
  76. :title="modalType == 'add' ? '添加产品' : '编辑产品'"
  77. v-model="dialogVisible"
  78. width="700"
  79. v-loading="submitLoading"
  80. destroy-on-close
  81. >
  82. <div class="public_height_dialog">
  83. <byForm
  84. :formConfig="formConfig"
  85. :formOption="formOption"
  86. v-model="formData.data"
  87. :rules="rules"
  88. ref="byform"
  89. >
  90. <template #nameEnglish>
  91. <div style="width: 100%">
  92. <el-form-item label="英文名" prop="nameEnglish">
  93. <el-input
  94. v-model="formData.data.nameEnglish"
  95. placeholder="请输入"
  96. onkeyup="value=value.replace(/[^\x00-\xff]/g, '')"
  97. ></el-input>
  98. <!-- @input="(val) => handleKeyup(val)" -->
  99. </el-form-item>
  100. </div>
  101. </template>
  102. <template #productPic>
  103. <div>
  104. <el-upload
  105. v-model:fileList="fileList"
  106. action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
  107. :data="uploadData"
  108. list-type="picture-card"
  109. :on-remove="handleRemove"
  110. :before-upload="handleBeforeUpload"
  111. :on-preview="handlePreview"
  112. accept=".gif, .jpeg, .jpg, .png"
  113. >
  114. <el-icon><Plus /></el-icon>
  115. </el-upload>
  116. </div>
  117. </template>
  118. </byForm>
  119. </div>
  120. <template #footer>
  121. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  122. <el-button
  123. type="primary"
  124. @click="submitForm('byform')"
  125. size="large"
  126. :loading="submitLoading"
  127. >确 定</el-button
  128. >
  129. </template>
  130. </el-dialog>
  131. <el-dialog
  132. title="导入产品"
  133. v-model="openExcelDialog"
  134. width="400"
  135. v-loading="excelLoading"
  136. >
  137. <el-upload
  138. :action="actionUrl + '/productInfo/excelImportByEhsd'"
  139. :headers="headers"
  140. :on-success="handleSuccess"
  141. :on-progress="handleProgress"
  142. :show-file-list="false"
  143. :on-error="handleError"
  144. accept=".xlsx"
  145. >
  146. <el-button type="primary">点击导入</el-button>
  147. </el-upload>
  148. <template #footer>
  149. <el-button @click="openExcelDialog = false" size="large"
  150. >取 消</el-button
  151. >
  152. </template>
  153. </el-dialog>
  154. </div>
  155. </template>
  156. <script setup>
  157. import { ElMessage, ElMessageBox } from "element-plus";
  158. import byTable from "@/components/byTable/index";
  159. import byForm from "@/components/byForm/index";
  160. import treeList from "@/components/product/treeList";
  161. import { getToken } from "@/utils/auth";
  162. const headers = ref({ Authorization: "Bearer " + getToken() });
  163. const actionUrl = import.meta.env.VITE_APP_BASE_API;
  164. const loading = ref(false);
  165. const submitLoading = ref(false);
  166. const treeListData = ref([]);
  167. const innerMethon = ref([]);
  168. const outsideMethon = ref([]);
  169. const productUnit = ref([]);
  170. const accountCurrency = ref([]);
  171. const sourceList = ref({
  172. data: [],
  173. pagination: {
  174. total: 3,
  175. pageNum: 1,
  176. pageSize: 10,
  177. type: "",
  178. productClassifyId: "",
  179. keyword: "",
  180. definition: "1",
  181. },
  182. });
  183. let dialogVisible = ref(false);
  184. let openExcelDialog = ref(false);
  185. let excelLoading = ref(false);
  186. let modalType = ref("add");
  187. let rules = ref({
  188. productClassifyId: [
  189. { required: true, message: "请选择产品分类", trigger: "change" },
  190. ],
  191. name: [{ required: true, message: "请输入产品名称", trigger: "blur" }],
  192. nameEnglish: [
  193. { required: true, message: "请输入产品英文名", trigger: "blur" },
  194. ],
  195. productLong: [
  196. { required: true, message: "请输入长 (cm)", trigger: "blur" },
  197. ],
  198. productWide: [
  199. { required: true, message: "请输入宽 (cm)", trigger: "blur" },
  200. ],
  201. productHigh: [
  202. { required: true, message: "请输入高 (cm)", trigger: "blur" },
  203. ],
  204. innerPackMethod: [
  205. { required: true, message: "请选择内包装方式", trigger: "change" },
  206. ],
  207. outerPackMethod: [
  208. { required: true, message: "请选择外包装方式", trigger: "change" },
  209. ],
  210. });
  211. const { proxy } = getCurrentInstance();
  212. const props = defineProps({
  213. selectStatus: Boolean,
  214. });
  215. const selectConfig = reactive([
  216. // {
  217. // label: "产品类型",
  218. // prop: "type",
  219. // data: [],
  220. // },
  221. ]);
  222. const config = computed(() => {
  223. return [
  224. {
  225. attrs: {
  226. label: "图片",
  227. slot: "pic",
  228. align: "center",
  229. width: 100,
  230. },
  231. },
  232. {
  233. attrs: {
  234. label: "产品编码",
  235. prop: "code",
  236. },
  237. },
  238. {
  239. attrs: {
  240. label: "产品名称",
  241. prop: "name",
  242. },
  243. },
  244. {
  245. attrs: {
  246. label: "尺寸",
  247. slot: "size",
  248. },
  249. },
  250. {
  251. attrs: {
  252. label: "销售指导价",
  253. slot: "price",
  254. width: 150,
  255. },
  256. },
  257. {
  258. attrs: {
  259. label: "成本价",
  260. slot: "costPrice",
  261. width: 150,
  262. },
  263. },
  264. {
  265. attrs: {
  266. label: "操作",
  267. width: "120",
  268. align: "center",
  269. },
  270. // 渲染 el-button,一般用在最后一列。
  271. renderHTML(row) {
  272. return [
  273. props.selectStatus
  274. ? {
  275. attrs: {
  276. label: "选择",
  277. type: "primary",
  278. text: true,
  279. },
  280. el: "button",
  281. click() {
  282. clickSelect(row);
  283. },
  284. }
  285. : {
  286. attrs: {
  287. label: "修改",
  288. type: "primary",
  289. text: true,
  290. },
  291. el: "button",
  292. click() {
  293. getDtl(row);
  294. },
  295. },
  296. props.selectStatus
  297. ? {}
  298. : {
  299. attrs: {
  300. label: "删除",
  301. type: "danger",
  302. text: true,
  303. },
  304. el: "button",
  305. click() {
  306. // 弹窗提示是否删除
  307. ElMessageBox.confirm(
  308. "此操作将永久删除该数据, 是否继续?",
  309. "提示",
  310. {
  311. confirmButtonText: "确定",
  312. cancelButtonText: "取消",
  313. type: "warning",
  314. }
  315. ).then(() => {
  316. // 删除
  317. proxy
  318. .post("/productInfo/delete", {
  319. id: row.id,
  320. })
  321. .then((res) => {
  322. ElMessage({
  323. message: "删除成功",
  324. type: "success",
  325. });
  326. getList();
  327. });
  328. });
  329. },
  330. },
  331. ];
  332. },
  333. },
  334. ];
  335. });
  336. const uploadData = ref({});
  337. const fileList = ref([]);
  338. const fileListCopy = ref([]);
  339. let formData = reactive({
  340. data: {},
  341. });
  342. const formOption = reactive({
  343. disabled: false,
  344. inline: true,
  345. labelWidth: 100,
  346. itemWidth: 100,
  347. rules: [],
  348. });
  349. const byform = ref(null);
  350. const formConfig = computed(() => {
  351. return [
  352. {
  353. type: "title",
  354. title: "基本信息",
  355. },
  356. {
  357. type: "treeSelect",
  358. prop: "productClassifyId",
  359. label: "产品分类",
  360. data: treeListData.value,
  361. itemWidth: 100,
  362. disabled: false,
  363. style: {
  364. width: "100%",
  365. },
  366. },
  367. {
  368. type: "input",
  369. prop: "name",
  370. label: "产品名称",
  371. itemWidth: 100,
  372. disabled: false,
  373. },
  374. {
  375. type: "slot",
  376. slotName: "nameEnglish",
  377. label: "",
  378. },
  379. {
  380. type: "slot",
  381. slotName: "productPic",
  382. prop: "fileList",
  383. label: "产品图片",
  384. },
  385. {
  386. type: "title",
  387. title: "价格信息",
  388. },
  389. {
  390. type: "selectInput",
  391. prop: "price",
  392. selectProp: "currency",
  393. label: "销售指导价",
  394. itemWidth: 50,
  395. style: {
  396. width: "100%",
  397. },
  398. data: accountCurrency.value,
  399. },
  400. {
  401. type: "selectInput",
  402. prop: "costPrice",
  403. selectProp: "costCurrency",
  404. label: "成本价",
  405. itemWidth: 50,
  406. style: {
  407. width: "100%",
  408. },
  409. data: accountCurrency.value,
  410. },
  411. {
  412. type: "title",
  413. title: "属性信息",
  414. },
  415. {
  416. type: "input",
  417. prop: "spec",
  418. label: "规格型号",
  419. itemWidth: 100,
  420. disabled: false,
  421. },
  422. {
  423. type: "input",
  424. prop: "productLong",
  425. label: "尺寸",
  426. itemWidth: 33.33,
  427. placeholder: "长(cm)",
  428. disabled: false,
  429. },
  430. {
  431. type: "input",
  432. prop: "productWide",
  433. label: " ",
  434. itemWidth: 33.33,
  435. placeholder: "宽(cm)",
  436. disabled: false,
  437. },
  438. {
  439. type: "input",
  440. prop: "productHigh",
  441. label: " ",
  442. itemWidth: 33.33,
  443. placeholder: "高(cm)",
  444. disabled: false,
  445. },
  446. {
  447. type: "select",
  448. prop: "innerPackMethod",
  449. label: "内包装方式",
  450. required: true,
  451. itemWidth: 50,
  452. multiple: true,
  453. data: innerMethon.value,
  454. filterable: true,
  455. placeholder: "内包装方式",
  456. style: {
  457. width: "100%",
  458. },
  459. disabled: false,
  460. },
  461. {
  462. type: "select",
  463. prop: "outerPackMethod",
  464. label: "外包装方式",
  465. required: true,
  466. itemWidth: 50,
  467. multiple: true,
  468. data: outsideMethon.value,
  469. filterable: true,
  470. placeholder: "外包装方式",
  471. style: {
  472. width: "100%",
  473. },
  474. disabled: false,
  475. },
  476. {
  477. type: "input",
  478. prop: "netWeight",
  479. label: "净重(kg)",
  480. itemWidth: 100,
  481. style: {
  482. width: "30%",
  483. },
  484. },
  485. {
  486. type: "input",
  487. prop: "hsCode",
  488. label: "海关编码",
  489. itemWidth: 100,
  490. style: {
  491. width: "30%",
  492. },
  493. disabled: false,
  494. },
  495. {
  496. type: "input",
  497. itemType: "textarea",
  498. prop: "remark",
  499. label: "备注",
  500. itemWidth: 100,
  501. },
  502. ];
  503. });
  504. const getList = async (req) => {
  505. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  506. loading.value = true;
  507. proxy
  508. .post("/productInfo/getConditionProductList", sourceList.value.pagination)
  509. .then(
  510. (message) => {
  511. sourceList.value.data = message.rows.map((x) => ({
  512. ...x,
  513. fileList: [],
  514. ...JSON.parse(x.ehsdJson),
  515. }));
  516. sourceList.value.pagination.total = message.total;
  517. setTimeout(() => {
  518. loading.value = false;
  519. }, 200);
  520. const productIdList = message.rows.map((x) => x.id);
  521. // 请求文件数据并回显
  522. if (productIdList.length > 0) {
  523. proxy
  524. .post("/fileInfo/getList", {
  525. businessIdList: productIdList,
  526. })
  527. .then((fileObj) => {
  528. for (let i = 0; i < sourceList.value.data.length; i++) {
  529. const e = sourceList.value.data[i];
  530. for (const key in fileObj) {
  531. if (e.id === key) {
  532. e.fileList = fileObj[key];
  533. }
  534. }
  535. }
  536. });
  537. }
  538. },
  539. (err) => {
  540. loading.value = false;
  541. }
  542. );
  543. };
  544. const treeChange = (e) => {
  545. sourceList.value.pagination.productClassifyId = e.id;
  546. getList({ productClassifyId: e.id });
  547. };
  548. const openModal = () => {
  549. dialogVisible.value = true;
  550. modalType.value = "add";
  551. formData.data = {
  552. definition: "1",
  553. outerPackMethod: [],
  554. innerPackMethod: [],
  555. fileList: [],
  556. fileListCopy: [],
  557. currency: "",
  558. costCurrency: "",
  559. };
  560. if (accountCurrency.value && accountCurrency.value.length > 0) {
  561. formData.data.currency = accountCurrency.value[0].value;
  562. formData.data.costCurrency = accountCurrency.value[0].value;
  563. }
  564. fileList.value = [];
  565. fileListCopy.value = [];
  566. };
  567. const openExcel = () => {
  568. openExcelDialog.value = true;
  569. };
  570. const needAtt = [
  571. "productClassifyId",
  572. "name",
  573. "spec",
  574. "remark",
  575. "fileList",
  576. "id",
  577. "unit",
  578. "definition",
  579. ];
  580. const submitForm = () => {
  581. byform.value.handleSubmit((valid) => {
  582. // if (!fileListCopy.value.length > 0) {
  583. // return ElMessage({
  584. // message: "请上传产品图片",
  585. // type: "info",
  586. // });
  587. // }
  588. let jsonObj = {};
  589. formData.data.fileList = fileListCopy.value.map((x) => ({
  590. id: x.id,
  591. fileName: x.fileName,
  592. }));
  593. for (const key in formData.data) {
  594. if (needAtt.includes(key)) {
  595. } else {
  596. jsonObj[key] = formData.data[key];
  597. delete formData.data[key];
  598. }
  599. }
  600. jsonObj.innerPackMethod = jsonObj.innerPackMethod.join(",");
  601. jsonObj.outerPackMethod = jsonObj.outerPackMethod.join(",");
  602. jsonObj.type = "1"; //1为公司产品库
  603. formData.data.ehsdJson = JSON.stringify(jsonObj);
  604. submitLoading.value = true;
  605. proxy.post(`/productInfo/${modalType.value}ByEhsd`, formData.data).then(
  606. (res) => {
  607. ElMessage({
  608. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  609. type: "success",
  610. });
  611. dialogVisible.value = false;
  612. submitLoading.value = false;
  613. getList();
  614. },
  615. (err) => {
  616. for (const key in jsonObj) {
  617. formData.data[key] = jsonObj[key];
  618. }
  619. formData.data.innerPackMethod =
  620. formData.data.innerPackMethod.split(",");
  621. formData.data.outerPackMethod =
  622. formData.data.outerPackMethod.split(",");
  623. submitLoading.value = false;
  624. }
  625. );
  626. });
  627. };
  628. const getTreeList = () => {
  629. proxy
  630. .post("/productClassify/tree", { parentId: "", name: "", definition: "1" })
  631. .then((message) => {
  632. treeListData.value = message;
  633. });
  634. };
  635. const getDtl = (row) => {
  636. modalType.value = "edit";
  637. proxy.post("/productInfo/detailByEhsd", { id: row.id }).then((res) => {
  638. res.definition = "1"; //产品
  639. let jsonObj = JSON.parse(res.ehsdJson);
  640. res = {
  641. ...res,
  642. currency: jsonObj.currency
  643. ? jsonObj.currency
  644. : accountCurrency.value[0].value,
  645. costCurrency: jsonObj.costCurrency
  646. ? jsonObj.costCurrency
  647. : accountCurrency.value[0].value,
  648. ...jsonObj,
  649. };
  650. if (res.innerPackMethod) {
  651. res.innerPackMethod = res.innerPackMethod.split(",");
  652. } else {
  653. res.innerPackMethod = [];
  654. }
  655. if (res.outerPackMethod) {
  656. res.outerPackMethod = res.outerPackMethod.split(",");
  657. } else {
  658. res.outerPackMethod = [];
  659. }
  660. formData.data = res;
  661. dialogVisible.value = true;
  662. proxy
  663. .post("/fileInfo/getList", { businessIdList: [row.id] })
  664. .then((fileObj) => {
  665. if (fileObj[row.id]) {
  666. fileList.value = fileObj[row.id].map((x) => ({
  667. ...x,
  668. url: x.fileUrl,
  669. }));
  670. fileListCopy.value = fileObj[row.id].map((x) => ({
  671. ...x,
  672. url: x.fileUrl,
  673. }));
  674. } else {
  675. fileList.value = [];
  676. fileListCopy.value = [];
  677. }
  678. });
  679. });
  680. };
  681. const isdisabled = ["price", "costPrice", "remark", "netWeight"];
  682. // watch(modalType, (val) => {
  683. // if (val) {
  684. // for (let i = 0; i < formConfig.value.length; i++) {
  685. // const element = formConfig.value[i];
  686. // if (element.type != "title" || element.type != "slot") {
  687. // if (!isdisabled.includes(element.prop)) {
  688. // element.disabled = val == "edit" ? true : false;
  689. // }
  690. // }
  691. // }
  692. // }
  693. // });
  694. const handleBeforeUpload = async (file) => {
  695. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  696. uploadData.value = res.uploadBody;
  697. fileListCopy.value.push({
  698. id: res.id,
  699. fileName: res.fileName,
  700. path: res.fileUrl,
  701. url: res.fileUrl,
  702. uid: file.uid,
  703. });
  704. };
  705. const handleRemove = (file) => {
  706. const index = fileListCopy.value.findIndex(
  707. (x) => x.uid === file.uid || x.id === file.id
  708. );
  709. fileListCopy.value.splice(index, 1);
  710. };
  711. const handleClickFile = (file) => {
  712. window.open(file.fileUrl, "_blank");
  713. };
  714. const handleProgress = () => {
  715. excelLoading.value = true;
  716. };
  717. const handleError = (err) => {
  718. ElMessage({
  719. message: `${err},请重试!`,
  720. type: "info",
  721. });
  722. openExcelDialog.value = false;
  723. excelLoading.value = false;
  724. };
  725. const handleSuccess = (res) => {
  726. if (res.code != 200) {
  727. return ElMessage({
  728. message: `${res.msg},请重试!`,
  729. type: "info",
  730. });
  731. } else {
  732. ElMessage({
  733. message: "导入成功!",
  734. type: "success",
  735. });
  736. openExcelDialog.value = false;
  737. excelLoading.value = false;
  738. getList();
  739. }
  740. };
  741. const getDict = () => {
  742. proxy
  743. .getDictOne([
  744. "inner_packaging_method_ehsd",
  745. "outside_packaging_method_ehsd",
  746. "unit",
  747. "account_currency",
  748. ])
  749. .then((res) => {
  750. innerMethon.value = res["inner_packaging_method_ehsd"].map((x) => ({
  751. label: x.dictValue,
  752. value: x.dictKey,
  753. }));
  754. outsideMethon.value = res["outside_packaging_method_ehsd"].map((x) => ({
  755. label: x.dictValue,
  756. value: x.dictKey,
  757. }));
  758. productUnit.value = res["unit"].map((x) => ({
  759. label: x.dictValue,
  760. value: x.dictKey,
  761. }));
  762. accountCurrency.value = res["account_currency"].map((x) => ({
  763. label: x.dictValue,
  764. value: x.dictKey,
  765. }));
  766. });
  767. };
  768. getDict();
  769. getTreeList();
  770. getList();
  771. const clickSelect = (item) => {
  772. proxy.$emit("selectProduct", item);
  773. };
  774. const handleKeypress = (event) => {
  775. // 判断输入字符是否为中文字符
  776. if (event.key.match(/[\u4e00-\u9fa5]/)) {
  777. // 阻止输入
  778. event.preventDefault();
  779. }
  780. };
  781. const handleKeyup = (val) => {
  782. // 过滤掉中文字符
  783. formData.data.nameEnglish = formData.data.nameEnglish.replace(
  784. /[\u4e00-\u9fa5]/g,
  785. ""
  786. );
  787. };
  788. const handlePreview = (file) => {
  789. if (file && file.fileUrl) {
  790. window.open(file.fileUrl, "_black");
  791. }
  792. };
  793. </script>
  794. <style lang="scss" scoped>
  795. .user {
  796. padding: 20px;
  797. display: flex;
  798. justify-content: space-between;
  799. .tree {
  800. width: 300px;
  801. }
  802. .content {
  803. width: calc(100% - 320px);
  804. }
  805. }
  806. .pic {
  807. object-fit: contain;
  808. width: 50px;
  809. height: 50px;
  810. cursor: pointer;
  811. vertical-align: middle;
  812. }
  813. </style>