detail.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. <template>
  2. <headerBar title="拍摄商品" :menu="[
  3. {
  4. type: 'setting'
  5. },
  6. {
  7. name: '详情高级配置',
  8. click: openPhotographySeniorDetail
  9. }
  10. ]" />
  11. <div class="detail-container">
  12. <div>
  13. <!-- 主图LOGO部分 -->
  14. <div class="logo-section flex left top">
  15. <div class="section-title">
  16. <img src="@/assets/images/Photography/zhuangshi.png" style="width: 32px; height: 32px;" />
  17. 主图LOGO:
  18. </div>
  19. <upload :value="form.logo_path" @input="onInput"></upload>
  20. </div>
  21. <el-divider />
  22. <!-- 图片抠图与货号图生成 -->
  23. <div class="section">
  24. <div class="section-title">
  25. <img src="@/assets/images/Photography/zhuangshi.png" style="width: 32px; height: 32px;" />
  26. 图片抠图与货号图生成
  27. </div>
  28. <div class="section-content">
  29. <div v-if="showTips" class="instruction-out flex top left">
  30. <img style="fill: #000" src="@/assets/images/xinxi.svg" />
  31. <ol class="instruction-list">
  32. <li>请在下方确认图片拍摄过程中的顺序,确保所有拍摄的图片的顺序一致。</li>
  33. <li>使用中英文语号分隔。</li>
  34. <li>图片的名称不能随意修改,否则无法正常生成详情页。</li>
  35. <li>现有图片名称有:俯视、侧视、后视、鞋底、内里</li>
  36. </ol>
  37. <el-icon @click="showTips = false" class="close-icon">
  38. <Close />
  39. </el-icon>
  40. </div>
  41. <!-- 货号文件夹 -->
  42. <!-- <div class="form-item">
  43. <div class="label">货号文件夹:</div>
  44. <div class="folder-warp">
  45. <div class="folder-input">
  46. <el-input style="width: 60%;" v-model="folderPath" type="textarea" :rows="2" readonly
  47. placeholder="请选择货号文件夹" />
  48. <el-button class="check-button" type="primary" @click="selectFolder">
  49. <img src="@/assets/images/Photography/wenjian.png" style="width: 14px; " />
  50. 选择目标文件夹</el-button>
  51. </div>
  52. <div class="hint">
  53. <el-icon>
  54. <Warning />
  55. </el-icon> <text>选择货号的上级文件夹</text>
  56. </div>
  57. </div>
  58. </div>
  59. -->
  60. </div>
  61. </div>
  62. <el-divider />
  63. <!-- 选择详情模板部分 -->
  64. <div class="template-section ">
  65. <div class="flex between">
  66. <div class="section-title">
  67. <img src="@/assets/images/Photography/zhuangshi.png" style="width: 32px; height: 32px;" />
  68. 选择详情模版
  69. </div>
  70. <div class="template-pagination">
  71. <el-pagination background layout="prev, pager, next" v-model:current-page="queryParams.current"
  72. v-model:page-size.sync="queryParams.size" :total="totalPage" @current-change="onCurrentChange"
  73. @size-change="onSizeChange" />
  74. </div>
  75. </div>
  76. <div class="template-list">
  77. <div v-for="(template, index) in visibleTemplates" :key="index" class="template-item"
  78. @click="form.selectTemplate = template">
  79. <el-image :src="template.template_cover_image" fit="contain" class="cur-p"
  80. style="width: 100%; display: block;" />
  81. <div class="select-warp" :class="form.selectTemplate.id == template.id ? 'active' : ''">
  82. <el-icon color="#FFFFFF">
  83. <Select />
  84. </el-icon>
  85. </div>
  86. <div class="template-info">
  87. <span class="mar-left-10 chaochu_1">{{ template.template_name }}</span>
  88. <div class="template-view" @click="viewTemplate(template)">查看</div>
  89. </div>
  90. </div>
  91. </div>
  92. </div>
  93. <el-divider />
  94. <!-- 详情高级配置 -->
  95. <div class="section">
  96. <div class="section-title">
  97. <img src="@/assets/images/Photography/zhuangshi.png" style="width: 32px; height: 32px;" />
  98. 详情高级配置
  99. </div>
  100. <div class="section-content">
  101. <!-- 图片顺序 -->
  102. <div class="form-item">
  103. <div class="label">图片顺序:</div>
  104. <el-input v-model="imageOrder" placeholder="请输入图片顺序" class="specific-page-input">
  105. <template #append>
  106. <el-button class="explain-btn" link type="primary">说明</el-button>
  107. </template>
  108. </el-input>
  109. </div>
  110. <!-- 同款检验 -->
  111. <!-- <div class="form-item">
  112. <div class="label">同款检验:</div>
  113. <el-checkbox v-model="checkSimilar">同款下货号必须齐全</el-checkbox>
  114. </div>
  115. -->
  116. <!-- 可指定页面独修改 -->
  117. <!-- <div class="form-item">
  118. <div class="label">可指定页面独修改:</div>
  119. <el-input v-model="specificPage" placeholder="请输入入需要单独修改的页面,示例:4:1 (需修改模版的编号:第一张)"
  120. class="specific-page-input">
  121. <template #append>
  122. <el-button class="explain-btn" link type="primary">说明</el-button>
  123. </template>
  124. </el-input>
  125. </div>
  126. -->
  127. </div>
  128. </div>
  129. <el-divider />
  130. <!-- 详情资料准备部分 -->
  131. <div class="data-prep-section">
  132. <div class="flex-item left">
  133. <div class="section-title">
  134. <img src="@/assets/images/Photography/zhuangshi.png" style="width: 32px; height: 32px;" />
  135. 详情资料准备 (2选1)
  136. </div>
  137. </div>
  138. <div class="flex-item left">
  139. <el-radio-group v-model="form.dataType" class="ml-4">
  140. <el-radio label="1" size="large">EXCEL文件选择</el-radio>
  141. <el-radio label="2" size="large">系统对接(和业务员联系)</el-radio>
  142. </el-radio-group>
  143. </div>
  144. <div v-if="form.dataType == '1'" class="excel-upload">
  145. <div class="flex bottom between">
  146. <div style="max-width: 160px;" class="mar-left-20">商品基础资料EXCEL文件选择:</div>
  147. <div class="flex bottom mar-left-20" style="flex-grow: 1;">
  148. <el-input type="textarea" v-model="form.excelFilePath" />
  149. </div>
  150. <el-button class="select-button button--primary1 mar-left-20" type="primary" @click="selectExcel">
  151. <img src="@/assets/images/Photography/wenjian.png" style="width: 16px; margin-right: 4px;" />
  152. 选择</el-button>
  153. </div>
  154. </div>
  155. </div>
  156. </div>
  157. <!-- 底部按钮 -->
  158. <div class="footer">
  159. <!-- <el-button class="button--primary1 footer-button" type="primary" @click="saveConfig">保存配置</el-button> -->
  160. <!-- <el-button class="button--primary1 footer-button" type="primary" @click="startProcess">开始处理</el-button> -->
  161. <el-button class="button--primary1 footer-button" type="primary" @click="generate">开始生成</el-button>
  162. </div>
  163. </div>
  164. <loading-dialog v-model="loadingDialogVisible" :progress="progress" :message="message" :show-button="showButton"
  165. @button-click="handleComplete" />
  166. <el-dialog v-model="dialogVisible">
  167. <img style="width: 100%;" :src="dialogImageUrl" alt="Preview Image" />
  168. </el-dialog>
  169. </template>
  170. <script lang="ts" setup>
  171. import { getCompanyTemplatesApi } from '@/apis/other'
  172. import tokenInfo from '@/stores/modules/token';
  173. import useUserInfo from "@/stores/modules/user";
  174. import { ElMessage, ElMessageBox } from 'element-plus'
  175. import headerBar from '@/components/header-bar/index.vue'
  176. import { ref, computed, reactive, onMounted } from 'vue';
  177. import { Select } from '@element-plus/icons-vue'
  178. import upload from '@/components/upload'
  179. import client from "@/stores/modules/client";
  180. import icpList from '@/utils/ipc'
  181. const clientStore = client();
  182. import { getRouterUrl } from '@/utils/appfun'
  183. import { useRouter } from "vue-router";
  184. import { Close, Warning } from '@element-plus/icons-vue'
  185. import LoadingDialog from '@/views/Photography/components/LoadingDialog.vue'
  186. const showTips = ref(true)
  187. const folderPath = ref('') //货号文件夹
  188. // const reportMode = ref('normal') // 抠图模式
  189. const imageOrder = ref('俯视、侧视、后跟、鞋底、内里、组合、组合2、组合3') // 图片顺序
  190. const checkSimilar = ref(false) // 同款检验
  191. const specificPage = ref('') // 可指定页面独修改
  192. // 路由和状态管理初始化
  193. const route = useRoute();
  194. const router = useRouter();
  195. // 完成目录
  196. const completeDirectory = ref('')
  197. const loadingDialogVisible = ref(false)
  198. const progress = ref(0)
  199. const message = ref('正在为您处理,请稍后')
  200. const showButton = ref(true)
  201. let templates = ref([])
  202. let goods_art_nos = ref([])
  203. // 状态变量
  204. const totalPage = ref(0);
  205. const itemsPerPage = 4; // 每页显示的模板数量
  206. const dialogVisible = ref(false);
  207. const dialogImageUrl = ref('');
  208. const queryParams = reactive({ // 分页查询参数
  209. size: 1,
  210. current: 1,
  211. })
  212. const form = reactive({
  213. selectTemplate: {}, //选中的模板
  214. dataType: '1', // 1: 选择excel文件 2: 系统对接
  215. logo_path: '', // 主图LOGO
  216. excelFilePath: 'D:\\MyDocuments\\PythonCode\\MyPython\\red_dragonfly\\deal_pics\\auto_capture_V2\\auto_photo', // 商品基础资料EXCEL文件选择
  217. })
  218. onMounted(() => {
  219. goods_art_nos.value = route.query.goods_art_nos
  220. getCompanyTemplates()
  221. })
  222. // 计算属性,获取当前页可见的模板
  223. const visibleTemplates = computed(() => {
  224. const startIndex = (queryParams.current - 1) * itemsPerPage;
  225. const data = templates.value.slice(startIndex, startIndex + itemsPerPage);
  226. return data
  227. });
  228. // 查看模板详情
  229. const viewTemplate = (template) => {
  230. // 展示大图
  231. dialogVisible.value = true
  232. dialogImageUrl.value = template.template_preview_image
  233. };
  234. // 获取模版列表
  235. const getCompanyTemplates = async () => {
  236. const { data } = await getCompanyTemplatesApi()
  237. templates.value = data.list
  238. // 默认选中第一个模板
  239. if (templates.value.length > 0) {
  240. form.selectTemplate = templates.value[0]
  241. }
  242. // 计算总页数
  243. totalPage.value = Math.ceil(templates.value.length / itemsPerPage);
  244. }
  245. const onCurrentChange = (page) => {
  246. queryParams.current = page;
  247. };
  248. const onSizeChange = (data) => {
  249. };
  250. // 开始生成操作
  251. const generate = async function () {
  252. const tokenInfoStore = tokenInfo();
  253. const token = tokenInfoStore.getToken; // 使用 getToken() 获取 token
  254. let temp_list = []
  255. templates.value.map(item => {
  256. temp_list.push({
  257. template_id: item.template_id,
  258. template_local_classes: item.template_local_classes,
  259. })
  260. })
  261. const params = {
  262. goods_art_no: goods_art_nos.value,
  263. logo_path: form.logo_path,
  264. temp_name: form.selectTemplate.template_id,
  265. excel_path: '',
  266. template_image_order: form.selectTemplate.template_image_order,
  267. temp_list,
  268. token,
  269. }
  270. loadingDialogVisible.value = true
  271. progress.value = 0
  272. showButton.value = true
  273. const interval = setInterval(() => {
  274. if (progress.value < 100) {
  275. progress.value += 10
  276. }
  277. }, 1000)
  278. clientStore.ipc.removeAllListeners(icpList.generate.generatePhotoDetail);
  279. clientStore.ipc.send(icpList.generate.generatePhotoDetail, params);
  280. clientStore.ipc.on(icpList.generate.generatePhotoDetail, (event, result) => {
  281. clientStore.ipc.removeAllListeners(icpList.generate.generatePhotoDetail);
  282. console.log("%c Line:306 🍻 result", "color:#42b983", result);
  283. clearInterval(interval)
  284. if (result.code === 0) {
  285. const href = result.data.out_put_dir
  286. completeDirectory.value = href
  287. progress.value = 100
  288. message.value = '全部处理完毕'
  289. showButton.value = false
  290. } else {
  291. showButton.value = false
  292. if (result.msg) {
  293. ElMessage.error(result.msg)
  294. }
  295. }
  296. });
  297. }
  298. const onInput = (value) => {
  299. form.logo_path = value
  300. }
  301. function selectExcel() {
  302. clientStore.ipc.removeAllListeners(icpList.utils.openFile);
  303. clientStore.ipc.send(icpList.utils.openFile, {
  304. filters: [
  305. { name: '支持xls,xlsx', extensions: ['xlsx', 'xls'] }
  306. ],
  307. title: "选择基础文件资料"
  308. });
  309. clientStore.ipc.on(icpList.utils.openFile, async (event, result) => {
  310. form.excelFilePath = result
  311. clientStore.ipc.removeAllListeners(icpList.utils.openFile);
  312. })
  313. }
  314. const Router = useRouter()
  315. //打开主图详情
  316. function openPhotographySeniorDetail() {
  317. const { href } = Router.resolve({
  318. name: 'PhotographySeniorDetail'
  319. })
  320. clientStore.ipc.removeAllListeners(icpList.utils.openMain);
  321. let params = {
  322. title: '详情高级配置',
  323. width: 1000,
  324. height: 630,
  325. frame: true,
  326. id: "PhotographySeniorDetail",
  327. url: getRouterUrl(href)
  328. }
  329. clientStore.ipc.send(icpList.utils.openMain, params);
  330. }
  331. const startProcess = () => {
  332. loadingDialogVisible.value = true
  333. progress.value = 0
  334. showButton.value = true
  335. // 模拟进度更新
  336. const interval = setInterval(() => {
  337. if (progress.value < 100) {
  338. progress.value += 10
  339. } else {
  340. clearInterval(interval)
  341. message.value = '全部处理完毕'
  342. showButton.value = false
  343. }
  344. }, 500)
  345. }
  346. const handleComplete = () => {
  347. loadingDialogVisible.value = false
  348. // 这里可以添加打开目录的逻辑
  349. // 打开目录
  350. clientStore.ipc.removeAllListeners(icpList.utils.openDirectory);
  351. console.log('打开目录')
  352. clientStore.ipc.removeAllListeners(icpList.utils.shellFun);
  353. let params = {
  354. action: 'openPath',
  355. params: completeDirectory.value
  356. // params: 'C:\Users\\21333\\Desktop\\HQT\\151405492752642685067862.jpg'
  357. }
  358. clientStore.ipc.send(icpList.utils.shellFun, params);
  359. }
  360. const selectFolder = () => {
  361. clientStore.ipc.removeAllListeners(icpList.utils.openDirectory);
  362. clientStore.ipc.send(icpList.utils.openDirectory);
  363. clientStore.ipc.on(icpList.utils.openDirectory, async (event, result) => {
  364. folderPath.value = result
  365. clientStore.ipc.removeAllListeners(icpList.utils.openDirectory);
  366. })
  367. }
  368. </script>
  369. <style lang="scss" scoped>
  370. .detail-container {
  371. background-color: #EAECED;
  372. width: 100%;
  373. min-width: 600px;
  374. padding: 20px;
  375. overflow: hidden;
  376. }
  377. .logo-section,
  378. .template-section,
  379. .data-prep-section {
  380. margin-bottom: 20px;
  381. }
  382. .logo-upload {
  383. border: 1px dashed #ccc;
  384. border-radius: 5px;
  385. padding: 50px 0;
  386. text-align: center;
  387. cursor: pointer;
  388. }
  389. .template-pagination button {
  390. margin-right: 5px;
  391. }
  392. .template-pagination span {
  393. display: inline-block;
  394. width: 20px;
  395. height: 20px;
  396. line-height: 20px;
  397. text-align: center;
  398. border: 1px solid #ccc;
  399. border-radius: 5px;
  400. margin-right: 5px;
  401. cursor: pointer;
  402. }
  403. .template-list {
  404. display: flex;
  405. flex-wrap: wrap;
  406. gap: 20px;
  407. margin-top: 10px;
  408. .template-item {
  409. width: calc(25% - 18px);
  410. border: 1px solid #ccc;
  411. border-radius: 10px;
  412. cursor: pointer;
  413. background: #f0f0f0;
  414. position: relative;
  415. overflow: hidden;
  416. .template-info {
  417. position: absolute;
  418. bottom: 0;
  419. left: 0;
  420. background: rgba($color: #000000, $alpha: .3);
  421. width: 100%;
  422. height: 36px;
  423. line-height: 36px;
  424. color: #eee;
  425. display: flex;
  426. align-items: center;
  427. justify-content: space-between;
  428. .template-view {
  429. background: #DFE2E3;
  430. color: #3366FF;
  431. height: 30px;
  432. line-height: 30px;
  433. padding: 0 10px;
  434. border-radius: 4px;
  435. margin-right: 10px;
  436. font-size: 14px;
  437. }
  438. }
  439. }
  440. }
  441. .excel-upload {
  442. width: 100%;
  443. background: #F7F7F7;
  444. padding: 20px 0;
  445. }
  446. .generate-button {
  447. padding: 10px 20px;
  448. color: white;
  449. border: none;
  450. border-radius: 5px;
  451. cursor: pointer;
  452. }
  453. .select-button {
  454. background: #DFE2E3 !important;
  455. color: #3366FF !important;
  456. height: 30px;
  457. line-height: 30px;
  458. padding: 0 10px;
  459. border-radius: 4px;
  460. margin-right: 10px;
  461. font-size: 14px;
  462. font-weight: 550;
  463. }
  464. .select-warp {
  465. width: 18px;
  466. height: 18px;
  467. border-radius: 4px;
  468. background-color: #fff;
  469. position: absolute;
  470. top: 10px;
  471. left: 10px;
  472. &.active {
  473. background-color: #1677FF;
  474. }
  475. }
  476. .section-title {
  477. display: flex;
  478. align-items: center;
  479. gap: 8px;
  480. font-weight: bold;
  481. margin-bottom: 16px;
  482. color: #474747;
  483. }
  484. .section {
  485. margin-bottom: 24px;
  486. .section-title {
  487. display: flex;
  488. align-items: center;
  489. gap: 8px;
  490. font-weight: bold;
  491. margin-bottom: 16px;
  492. color: #474747;
  493. }
  494. .section-content {
  495. padding-left: 16px;
  496. }
  497. }
  498. .instruction-out {
  499. background: #EAF3FF;
  500. border-radius: 4px;
  501. border: 1px solid #CBE1FF;
  502. padding: 10px 20px;
  503. width: 80%;
  504. position: relative;
  505. .instruction-list {
  506. margin: 0px 0 0 10px;
  507. padding-left: 20px;
  508. padding-right: 40px;
  509. width: 100%;
  510. li {
  511. margin-bottom: 4px;
  512. text-align: left;
  513. font-size: 14px;
  514. }
  515. }
  516. .close-icon {
  517. position: absolute;
  518. top: 12px;
  519. right: 19px;
  520. }
  521. }
  522. .form-item {
  523. margin: 16px 0;
  524. display: flex;
  525. .label {
  526. min-width: 120px;
  527. margin-right: 12px;
  528. }
  529. .folder-warp {
  530. width: 100%;
  531. display: flex;
  532. flex-direction: column;
  533. .folder-input {
  534. flex: 1;
  535. display: flex;
  536. align-items: center;
  537. .check-button {
  538. background: #DFE2E3;
  539. border-radius: 6px;
  540. padding: 6px 12px;
  541. color: #2957FF;
  542. margin-left: 20px;
  543. }
  544. }
  545. }
  546. .hint {
  547. text-align: left;
  548. color: #999;
  549. margin-top: 6px;
  550. font-size: 14px;
  551. color: #FF4C00;
  552. font-style: normal;
  553. }
  554. .specific-page-input {
  555. flex: 1;
  556. }
  557. }
  558. .image-order {
  559. flex: 1;
  560. display: flex;
  561. justify-content: space-between;
  562. align-items: center;
  563. }
  564. .footer {
  565. display: flex;
  566. justify-content: center;
  567. margin-top: 24px;
  568. .footer-button {
  569. padding: 10px 20px;
  570. }
  571. }
  572. .explain-btn {
  573. padding-left: 20px;
  574. padding-right: 20px;
  575. color: #2957FF !important;
  576. }
  577. </style>