perfectStore.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. <template>
  2. <div class="perfectStore">
  3. <!-- 顶部条-->
  4. <van-nav-bar class="navBar" title="AI完美门店报告" left-arrow @click-left="onClickLeft">
  5. <template #right v-if="list">
  6. <template v-if="list.wanmeiStore">
  7. <span
  8. style="
  9. color: white;
  10. background: #74a4d9;
  11. display: block;
  12. padding: 6px 10px;
  13. border-radius: 6px;
  14. "
  15. @click="editorFn"
  16. v-if="!remarkShow && sameDay"
  17. >编辑
  18. </span>
  19. </template>
  20. <template v-else>
  21. <!-- 新的生成中动画组件 -->
  22. <div class="ai-generating">
  23. <!-- AI 星星图标 -->
  24. <div class="ai-icon">
  25. <svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
  26. <defs>
  27. <linearGradient id="starGrad" x1="0%" y1="0%" x2="100%" y2="100%">
  28. <stop offset="0%" stop-color="#6366f1" />
  29. <stop offset="100%" stop-color="#a855f7" />
  30. </linearGradient>
  31. </defs>
  32. <!-- 大星星 -->
  33. <path
  34. d="M10 2 L11.2 7.8 L17 9 L11.2 10.2 L10 16 L8.8 10.2 L3 9 L8.8 7.8 Z"
  35. fill="url(#starGrad)"
  36. style="
  37. animation: starPulse 1.8s ease-in-out infinite;
  38. transform-origin: 10px 9px;
  39. ">
  40. <animateTransform
  41. attributeName="transform"
  42. type="scale"
  43. values="1;1.12;1"
  44. dur="1.8s"
  45. repeatCount="indefinite"
  46. additive="sum"
  47. calcMode="ease" />
  48. </path>
  49. <!-- 小星星 -->
  50. <circle cx="15.5" cy="4.5" r="1.5" fill="#a855f7" opacity="0.7">
  51. <animate
  52. attributeName="opacity"
  53. values="0.4;1;0.4"
  54. dur="1.4s"
  55. repeatCount="indefinite" />
  56. <animate
  57. attributeName="r"
  58. values="1.2;1.8;1.2"
  59. dur="1.4s"
  60. repeatCount="indefinite" />
  61. </circle>
  62. <!-- 微星 -->
  63. <circle cx="4.5" cy="14.5" r="1" fill="#6366f1" opacity="0.5">
  64. <animate
  65. attributeName="opacity"
  66. values="0.3;0.9;0.3"
  67. dur="1.8s"
  68. begin="0.5s"
  69. repeatCount="indefinite" />
  70. <animate
  71. attributeName="r"
  72. values="0.8;1.4;0.8"
  73. dur="1.8s"
  74. begin="0.5s"
  75. repeatCount="indefinite" />
  76. </circle>
  77. </svg>
  78. </div>
  79. <!-- 三个跳动点 -->
  80. <div class="dots-container">
  81. <div class="dot"></div>
  82. <div class="dot"></div>
  83. <div class="dot"></div>
  84. </div>
  85. <!-- 渐变文字 -->
  86. <span class="gen-text">生成中</span>
  87. </div>
  88. <!-- <span style="font-size: 18px; color: #1989fa; display: flex; align-items: center"
  89. ><img width="35px" :src="require('@/assets/wanmeiStoreImg.gif')" />生成中</span
  90. > -->
  91. </template>
  92. </template>
  93. </van-nav-bar>
  94. <!-- 主体内容-->
  95. <div class="container" v-if="list">
  96. <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
  97. <div class="lineGrey"></div>
  98. <div class="card mt10">
  99. <div class="title">
  100. {{ list.storeName }}(<span style="color: #1989fa">{{ list.storeCode }}</span
  101. >)
  102. </div>
  103. <div class="subtitle">地址:{{ list.addressLine }}</div>
  104. <div class="subtitle">拜访人:{{ list.nickName }}</div>
  105. <div class="subtitle">拜访日期:{{ list.startTime }}~{{ list.stopTime }}</div>
  106. <div class="subtitle" v-if="list.dwellTime">拜访时长:{{ list.dwellTime }}</div>
  107. <!-- 分销店 -->
  108. <template
  109. v-if="
  110. verifyStoreType(list.storeCategory) &&
  111. verifyStoreType(list.storeCategory).type == 'fxd'
  112. ">
  113. <div class="subtitle" style="display: flex">
  114. <div class="label" style="width: 75px">经销商:</div>
  115. <div class="valuue TCFXList">
  116. <div
  117. class="sfaStoreChainsContactList"
  118. v-for="(item, index) in list.sfaStoreChainsContactList"
  119. :key="index">
  120. {{ item.categoryDescribe }}
  121. {{ item.chainCode }}
  122. {{ item.chainName }}
  123. </div>
  124. </div>
  125. </div>
  126. </template>
  127. <template v-else>
  128. <div class="subtitle">经销商:{{ list.chainName }}</div>
  129. </template>
  130. <div class="subtitle" v-if="updateTimeShow">更新时间:{{ list.updateTime }}</div>
  131. </div>
  132. <!-- 特殊任务展示 -->
  133. <!-- 店招 -->
  134. <div class="shopSign specialTask" v-if="shopSignDetail && shopSignDetail.qualifiedState">
  135. <div class="specialTaskLeft" @click="openPerfectStoreSign(shopSignDetail)">
  136. <div class="SignText">AI 店招识别</div>
  137. <div class="signContent">
  138. <div class="" style="display: flex">
  139. <template v-if="shopSignDetail.qualifiedState != null">
  140. <van-button round type="primary" v-if="shopSignDetail.qualifiedState == '1'"
  141. >通过</van-button
  142. >
  143. <van-button round type="danger" v-else-if="shopSignDetail.qualifiedState == '0'"
  144. >不通过</van-button
  145. >
  146. <div class="jiantou">
  147. <van-icon name="arrow" />
  148. </div>
  149. </template>
  150. <template v-else>
  151. <span class="AISpan">AI识别中</span>
  152. </template>
  153. </div>
  154. </div>
  155. </div>
  156. </div>
  157. <!-- 调色机 -->
  158. <div class="TSJBox specialTask" v-if="tiaoSJDetail">
  159. <div class="specialTaskLeft" @click="openPerfectStoreTSJ(tiaoSJDetail)">
  160. <div class="SignText">AI 调色机识别</div>
  161. <div class="signContent">
  162. <div class="" style="display: flex">
  163. <template v-if="tiaoSJDetail.qualifiedState != null">
  164. <van-button round type="primary" v-if="tiaoSJDetail.qualifiedState == '1'"
  165. >通过</van-button
  166. >
  167. <van-button round type="danger" v-if="tiaoSJDetail.qualifiedState == '0'"
  168. >不通过</van-button
  169. >
  170. <div class="jiantou">
  171. <van-icon name="arrow" />
  172. </div>
  173. </template>
  174. <template v-else>
  175. <span class="AISpan">AI识别中</span>
  176. </template>
  177. </div>
  178. </div>
  179. </div>
  180. </div>
  181. <!-- 陈列SKU个数: -->
  182. <div class="TSJBox specialTask" v-if="list.isSku == '是'">
  183. <div class="specialTaskLeft">
  184. <div class="SignText">
  185. AI SKU个数识别: <span v-if="list.skuNum">{{ list.skuNum }}个</span>
  186. </div>
  187. <div class="signContent" @click="toSkuRecognize">
  188. <div class="" style="display: flex">
  189. <template v-if="list.wanmeiStore">
  190. <span style="color: rgb(25, 137, 250)">查看详情</span>
  191. <div class="jiantou">
  192. <van-icon name="arrow" />
  193. </div>
  194. </template>
  195. <template v-else>
  196. <span class="AISpan">AI识别中</span>
  197. </template>
  198. </div>
  199. </div>
  200. </div>
  201. </div>
  202. <!-- 目前陈列任务 -->
  203. <div class="TSJBox specialTask" v-if="taskTypeArr && taskTypeArr.length">
  204. <div class="specialTaskLeft">
  205. <div class="SignText">AI 陈列任务识别</div>
  206. </div>
  207. </div>
  208. <div class="SKUBox" v-if="taskTypeArr && taskTypeArr.length">
  209. <div class="SKUList">
  210. <div
  211. class="itemList"
  212. v-for="(value, index) in taskTypeArr"
  213. @click="historiStoreVisit(value)">
  214. <div class="itemTitle">{{ convertToChinese(index + 1) }}、{{ value.taskName }}</div>
  215. <div class="" style="display: flex">
  216. <template v-if="value.taskPhotoConditionPassed != null">
  217. <van-button round type="primary" v-if="value.taskPhotoConditionPassed == 1"
  218. >通过</van-button
  219. >
  220. <van-button round type="danger" v-if="value.taskPhotoConditionPassed == 0"
  221. >不通过</van-button
  222. >
  223. <div class="jiantou">
  224. <van-icon name="arrow" />
  225. </div>
  226. </template>
  227. <template v-else>
  228. <span class="AISpan">AI识别中</span>
  229. </template>
  230. </div>
  231. </div>
  232. </div>
  233. </div>
  234. <div style="padding: 15px 16px; font-size: 16px; font-weight: bold; background: #f5f5f5">
  235. 其他拜访任务
  236. </div>
  237. <div class="card" v-if="list.visitSource != 2">
  238. <div
  239. class="info"
  240. style="
  241. font-size: 14px;
  242. display: flex;
  243. align-items: center;
  244. justify-content: space-between;
  245. padding: 3px;
  246. "
  247. v-for="(item, index) in list.sfaTaskList"
  248. :key="index"
  249. v-if="
  250. item.photoIdentifyType != '1' && item.photoIdentifyType != '3' && item.taskType != '5'
  251. "
  252. @click="historiStoreVisit(item, index)">
  253. <p style="flex: 1; margin: 0">
  254. {{ item.taskName }}
  255. </p>
  256. <div class="taskPhotoConditionPassed" @click.stop>
  257. <el-popover
  258. :popper-class="item.taskPhotoConditionPassed == 1 ? 'zpoverSuccess' : 'zpover'"
  259. placement="bottom"
  260. width="120"
  261. trigger="click"
  262. :content="
  263. item.taskPhotoConditionPassed == 1
  264. ? '陈列奖励案拍照AI识别通过'
  265. : '陈列奖励案拍照AI识别不通过'
  266. ">
  267. <div class="taskPhotoConditionPassed" slot="reference">
  268. <img
  269. v-if="item.taskPhotoConditionPassed == 1"
  270. :src="require('@/assets/taskPhotoSu.png')" />
  271. <img
  272. v-if="item.taskPhotoConditionPassed == 0"
  273. :src="require('@/assets/taskPhotoErr.png')" />
  274. </div>
  275. </el-popover>
  276. </div>
  277. <p class="arrowdetils1">
  278. <van-icon name="arrow" />
  279. </p>
  280. </div>
  281. </div>
  282. </van-pull-refresh>
  283. </div>
  284. </div>
  285. </template>
  286. <script>
  287. import deleteUploadImg from '@/components/deleteUploadImg';
  288. import {
  289. getVisitsDetailPerfectStore,
  290. getPhotoTypeList1,
  291. insertVisitRemark,
  292. getListHistoryList,
  293. } from '@/api/index';
  294. import { getDictOption } from '@/api/index';
  295. import { ImagePreview } from 'vant';
  296. export default {
  297. components: { deleteUploadImg },
  298. data() {
  299. return {
  300. userShow: false,
  301. visitsId: '',
  302. imgs: '',
  303. typeList: [],
  304. active: ['1'],
  305. sameDay: false,
  306. ListHistoryTOTLE: '',
  307. managerRemarkContents: null,
  308. managerRemarkContent: '',
  309. CWShow: false,
  310. dataform: {
  311. remarkContent: '',
  312. visitsId: 0,
  313. },
  314. updateTimeShow: false,
  315. insert: true,
  316. remarkShow: false,
  317. ListHistoryList: [],
  318. list: null,
  319. AIResultOption: [],
  320. shopSignDetail: null,
  321. tiaoSJDetail: null,
  322. taskTypeArr: null,
  323. refreshing: false,
  324. };
  325. },
  326. activated() {
  327. this.list = null;
  328. this.toastLoading(0, '加载中...', true);
  329. this.visitsId = this.$route.query.visitId;
  330. this.dataform.visitsId = this.$route.query.visitId;
  331. this.getVisitsDetailFn();
  332. // 获取店招异常原因字典
  333. getDictOption({}, 'feedback_error_msg').then((res) => {
  334. this.AIResultOption = res.data;
  335. });
  336. this.getPhotoTypeList();
  337. },
  338. methods: {
  339. onRefresh() {
  340. this.refreshing = true;
  341. this.toastLoading(0, '加载中...', true);
  342. this.getVisitsDetailFn();
  343. },
  344. resultCorrect(resultCorrect) {
  345. let data = this.AIResultOption.find((item) => item.dictValue == resultCorrect);
  346. return data ? data.dictLabel : '';
  347. },
  348. filterTitle(item) {
  349. switch (item) {
  350. case 1:
  351. return '店招识别异常,主管反馈:';
  352. // case '2':
  353. // return '门店代码识别';
  354. case 3:
  355. return '调色机识别异常,主管反馈:';
  356. // case '4':
  357. // return '更换店招';
  358. }
  359. },
  360. getListHistoryList(instanceId) {
  361. var form = { visitsId: this.$route.query.visitId, pageNum: 1, pageSize: 999 };
  362. getListHistoryList(form).then((res) => {
  363. this.ListHistoryList = res.data;
  364. });
  365. },
  366. formatter(value) {
  367. return value.replace(
  368. /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/gi,
  369. '',
  370. );
  371. },
  372. editorFn() {
  373. if (this.list.hideStr != '' && this.list.hideStr != null) {
  374. this.$toast(this.list.hideStr);
  375. } else {
  376. localStorage.setItem('ORGName', this.list.deptName);
  377. localStorage.setItem('chainNameR', this.list.storeName);
  378. localStorage.setItem('getRequestFlage', 'true');
  379. if (this.list.visitSource == '2') {
  380. this.$router.push({
  381. path: '/abnormalVisit',
  382. query: {
  383. type: 'edit',
  384. storeCode: this.$route.query.storeCode || this.list.storeCode,
  385. rdId: this.$route.query.visitId,
  386. visitId: this.$route.query.visitId,
  387. storeId: this.list.storeId,
  388. visitSource: this.list.visitSource,
  389. visitModel: this.list.visitModel,
  390. marklat: this.list.lat,
  391. marklon: this.list.lon,
  392. },
  393. });
  394. } else {
  395. var LCshow = false;
  396. if (this.$route.query.taskId != null) {
  397. LCshow = true;
  398. } else {
  399. LCshow = false;
  400. }
  401. this.$router.push({
  402. path: '/storeVisitpage',
  403. query: {
  404. type: 'edit',
  405. storeGroupId: this.list.storeGroupId,
  406. storeCode: this.$route.query.storeCode || this.list.storeCode,
  407. storeName: this.list.storeName,
  408. addressLine: this.list.addressLine,
  409. rdId: this.$route.query.visitId,
  410. visitId: this.$route.query.visitId,
  411. storeId: this.list.storeId,
  412. visitSource: this.list.visitSource,
  413. visitModel: this.list.visitModel,
  414. LCshow: LCshow,
  415. instanceId: this.list.instanceId,
  416. taskId: this.$route.query.taskId,
  417. marklat: this.list.lat,
  418. marklon: this.list.lon,
  419. from: 'outPlan',
  420. },
  421. });
  422. }
  423. }
  424. },
  425. submint() {
  426. if (this.dataform.remarkContent.trim() == '') {
  427. this.$toast('请填写点评内容!');
  428. } else {
  429. insertVisitRemark(this.dataform).then((res) => {
  430. if (res.code == 200) {
  431. this.getVisitsDetailFn();
  432. }
  433. });
  434. }
  435. },
  436. getPhotoTypeList() {
  437. getPhotoTypeList1({}).then((res) => {
  438. this.typeList = res.data;
  439. });
  440. },
  441. getVisitsDetailFn() {
  442. this.shopSignDetail = null;
  443. this.tiaoSJDetail = null;
  444. this.taskTypeArr = null;
  445. getVisitsDetailPerfectStore({ visitsId: this.$route.query.visitId }).then((res) => {
  446. this.toastLoading().clear();
  447. if (this.refreshing) {
  448. this.refreshing = false;
  449. }
  450. if (res.code == 200) {
  451. this.list = res.data;
  452. this.filterSfaTaskList(this.list.sfaTaskList);
  453. let shopSignArr = this.list.sfaTaskList.filter((val) => val.photoIdentifyType == '1');
  454. if (shopSignArr.length) this.shopSignDetail = shopSignArr[0];
  455. let tiaoSJArr = this.list.sfaTaskList.filter((val) => val.photoIdentifyType == '3');
  456. if (tiaoSJArr.length) {
  457. let TSJqualifiedState0 = tiaoSJArr.filter((val) => val.qualifiedState == '0');
  458. let TSJqualifiedState1 = tiaoSJArr.filter((val) => val.qualifiedState == '1');
  459. if (TSJqualifiedState0 && TSJqualifiedState0.length) {
  460. this.tiaoSJDetail = TSJqualifiedState0[0];
  461. } else if (TSJqualifiedState1 && TSJqualifiedState1.length) {
  462. this.tiaoSJDetail = TSJqualifiedState1[0];
  463. } else {
  464. this.tiaoSJDetail = tiaoSJArr[0];
  465. }
  466. console.log(this.tiaoSJDetail);
  467. }
  468. if (res.data.visitSource != 2) {
  469. this.getListHistoryList(res.data.instanceId);
  470. }
  471. if (res.data.stopTime != res.data.updateTime) {
  472. this.updateTimeShow = true;
  473. } else {
  474. this.updateTimeShow = false;
  475. }
  476. if (localStorage.getItem('userId') == this.$route.query.userId) {
  477. this.userShow = true;
  478. } else {
  479. this.userShow = false;
  480. }
  481. if (this.$route.query.taskId != null) {
  482. this.CWShow = true;
  483. } else {
  484. this.CWShow = false;
  485. }
  486. this.sameDay = res.data.sameDay;
  487. if (localStorage.getItem('userId') == res.data.userId) {
  488. this.remarkShow = false;
  489. } else {
  490. this.remarkShow = true;
  491. }
  492. if (res.data.visitRemarks != null) {
  493. if (res.data.visitRemarks.length > 0) {
  494. this.managerRemarkContents = res.data.visitRemarks;
  495. } else {
  496. this.managerRemarkContents = null;
  497. }
  498. }
  499. if (res.data.visitSource == 2) {
  500. this.imgs = res.data.sysFileInfos;
  501. }
  502. } else {
  503. this.$toast.fail(res.msg);
  504. }
  505. });
  506. },
  507. filterSfaTaskList(list) {
  508. this.taskTypeArr = list.filter((val) => val.taskType == '5');
  509. },
  510. historiStoreVisit(val, index) {
  511. if (val.taskType == '5') {
  512. if (val.taskPhotoConditionPassed == null) {
  513. return;
  514. }
  515. this.$router.push({
  516. path: '/perfectStoreTask',
  517. query: {
  518. storeCode: this.$route.query.storeCode || this.list.storeCode,
  519. visitsId: this.visitsId,
  520. taskId: val.taskId,
  521. storeGroupId: this.list.storeGroupId,
  522. insert: 0,
  523. source: 'historicalDetails',
  524. },
  525. });
  526. } else {
  527. this.$router.push({
  528. path: '/historiStoreVisit',
  529. query: { visitId: this.visitsId, ids: index, taskType: val.taskType, taskId: val.taskId },
  530. });
  531. }
  532. sessionStorage.setItem('collectionItemList', JSON.stringify(val.collectionItemList));
  533. },
  534. toSkuRecognize() {
  535. if (this.list.wanmeiStore) {
  536. this.$router.push({
  537. path: '/perfectStoreSku',
  538. query: { visitId: this.visitsId },
  539. });
  540. }
  541. },
  542. onClickLeft() {
  543. if (this.$route.query.token) {
  544. this.$router.push({
  545. path: '/historicalVisit',
  546. });
  547. } else {
  548. this.$router.go(-1);
  549. }
  550. },
  551. previewsImg(url) {
  552. ImagePreview([url]);
  553. },
  554. openPerfectStoreSign(val) {
  555. if (val.qualifiedState == null) {
  556. return;
  557. }
  558. this.$router.push({
  559. path: '/perfectStoreSign',
  560. query: { visitId: this.visitsId, taskId: val.taskId },
  561. });
  562. },
  563. openPerfectStoreTSJ(val) {
  564. if (val.qualifiedState == null) {
  565. return;
  566. }
  567. let tiaoSJArr = this.list.sfaTaskList.filter((val) => val.photoIdentifyType == '3');
  568. let taskIds = tiaoSJArr.map((item) => item.taskId).join(',');
  569. this.$router.push({
  570. path: '/perfectStoreTSJ',
  571. query: { visitId: this.visitsId, taskId: taskIds },
  572. });
  573. },
  574. },
  575. };
  576. </script>
  577. <style lang="scss" scoped>
  578. .perfectStore {
  579. background: #fff;
  580. .specialTask {
  581. display: flex;
  582. flex-direction: row;
  583. margin: 10px;
  584. border-radius: 10px;
  585. // min-height: 90px;
  586. padding: 10px 0px 10px 10px;
  587. font-size: 16px;
  588. justify-content: space-between;
  589. background: #e5faff;
  590. .specialTaskLeft {
  591. display: flex;
  592. flex-direction: row;
  593. justify-content: space-between;
  594. width: 100%;
  595. }
  596. .SignText {
  597. font-weight: 600;
  598. }
  599. .signContent {
  600. display: flex;
  601. flex-direction: row;
  602. margin: 0 8px;
  603. .icon {
  604. padding-top: 2px;
  605. margin-right: 5px;
  606. }
  607. }
  608. }
  609. // .shopSign {
  610. // background: #e5faff;
  611. // }
  612. // .TSJBox {
  613. // background: #fff4e4;
  614. // margin-top: 20px;
  615. // }
  616. .SKUBox {
  617. margin: 0px 10px 10px 10px;
  618. border-radius: 10px;
  619. // min-height: 90px;
  620. padding: 5px 10px;
  621. font-size: 16px;
  622. // background: #ffecf4;
  623. .SKUTotal {
  624. display: flex;
  625. justify-content: space-between;
  626. width: 100%;
  627. color: rgb(25, 137, 250);
  628. }
  629. .SKUList {
  630. .itemList {
  631. display: flex;
  632. flex-direction: row;
  633. justify-content: space-between;
  634. align-items: center;
  635. padding: 3px 0;
  636. margin: 10px 0;
  637. }
  638. }
  639. }
  640. .itemList,
  641. .signContent {
  642. .itemTitle {
  643. flex: 1;
  644. // text-decoration: underline;
  645. // color: rgb(25, 137, 250);
  646. }
  647. .jiantou {
  648. margin-left: 5px;
  649. color: rgb(25, 137, 250);
  650. display: flex;
  651. align-items: center;
  652. }
  653. button {
  654. width: 55px;
  655. height: 25px;
  656. padding: 0;
  657. font-size: 12px;
  658. }
  659. }
  660. }
  661. .container {
  662. padding-bottom: 50px;
  663. }
  664. .container .custom-titles {
  665. white-space: break-spaces;
  666. }
  667. .card {
  668. background: #fff;
  669. padding: 10px 15px;
  670. box-sizing: border-box;
  671. .title {
  672. line-height: 30px;
  673. font-size: 16px;
  674. font-weight: bold;
  675. color: #333;
  676. }
  677. .subtitle {
  678. line-height: 24px;
  679. font-size: 14px;
  680. color: #7b7b7b;
  681. }
  682. .info {
  683. font-size: 16px;
  684. color: #484848;
  685. line-height: 40px;
  686. border-bottom: 1px solid #dedede;
  687. position: relative;
  688. &:last-child {
  689. border-bottom: 0;
  690. }
  691. .arrow {
  692. float: right;
  693. display: inline-block;
  694. height: 20px;
  695. width: 20px;
  696. line-height: 20px;
  697. text-align: center;
  698. border-radius: 50%;
  699. background: #1989fa;
  700. color: #fff;
  701. font-weight: bold;
  702. font-size: 14px;
  703. margin-top: 9px;
  704. }
  705. .taskPhotoConditionPassed {
  706. width: 33px;
  707. margin: 0 5px;
  708. display: inline-flex;
  709. img {
  710. width: 33px;
  711. height: 25px;
  712. }
  713. }
  714. .arrowdetils1 {
  715. background: #fff;
  716. color: #444;
  717. margin: 0;
  718. margin-left: 5px;
  719. }
  720. }
  721. }
  722. .TCFXList {
  723. .van-field__control--custom {
  724. flex-direction: column;
  725. align-items: self-start;
  726. .TCFXListTreeSelec {
  727. padding: 3px;
  728. }
  729. }
  730. }
  731. </style>
  732. <style lang="scss">
  733. .fontWeit .van-cell__title {
  734. font-weight: bold;
  735. font-size: 16px;
  736. }
  737. .fontWeit .van-cell__title p {
  738. margin: 0;
  739. }
  740. .comment .van-field__control {
  741. background-color: #ebf4ff;
  742. border-radius: 6px;
  743. }
  744. .contern .van-cell {
  745. background-color: #ebf4ff;
  746. border-radius: 6px;
  747. overflow: hidden;
  748. }
  749. .perfectStore {
  750. .card {
  751. .el-popover__reference-wrapper {
  752. display: flex;
  753. }
  754. }
  755. .van-button--danger {
  756. background-color: #ee0a24 !important;
  757. border: 1px solid #ee0a24 !important;
  758. }
  759. }
  760. .zpoverSuccess {
  761. background-color: #28e978 !important;
  762. color: #fff !important;
  763. padding: 8px 10px !important;
  764. z-index: 1 !important;
  765. border-radius: 6px !important;
  766. border: 0 !important;
  767. box-shadow: none !important;
  768. }
  769. .perfectStore {
  770. /* ===== AI 生成中动画 ===== */
  771. .ai-generating {
  772. display: flex;
  773. align-items: center;
  774. gap: 5px;
  775. background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(168, 85, 247, 0.08));
  776. border: 1px solid rgba(99, 102, 241, 0.2);
  777. border-radius: 20px;
  778. padding: 3px 10px 3px 7px;
  779. margin-right: -3px;
  780. }
  781. /* AI 图标 - 彩色渐变扫描动效 */
  782. .ai-icon {
  783. width: 20px;
  784. height: 20px;
  785. position: relative;
  786. flex-shrink: 0;
  787. }
  788. .ai-icon svg {
  789. width: 20px;
  790. height: 20px;
  791. }
  792. /* 三个跳动圆点 */
  793. .dots-container {
  794. display: flex;
  795. align-items: center;
  796. gap: 3px;
  797. }
  798. .dot {
  799. width: 5px;
  800. height: 5px;
  801. border-radius: 50%;
  802. background: linear-gradient(135deg, #6366f1, #a855f7);
  803. animation: dotBounce 1.4s ease-in-out infinite;
  804. }
  805. .dot:nth-child(1) {
  806. animation-delay: 0s;
  807. }
  808. .dot:nth-child(2) {
  809. animation-delay: 0.2s;
  810. }
  811. .dot:nth-child(3) {
  812. animation-delay: 0.4s;
  813. }
  814. @keyframes dotBounce {
  815. 0%,
  816. 60%,
  817. 100% {
  818. transform: translateY(0);
  819. opacity: 0.5;
  820. }
  821. 30% {
  822. transform: translateY(-5px);
  823. opacity: 1;
  824. }
  825. }
  826. /* 生成中文字 */
  827. .gen-text {
  828. font-size: 12px;
  829. font-weight: 500;
  830. background: linear-gradient(90deg, #6366f1, #a855f7, #6366f1);
  831. background-size: 200% auto;
  832. -webkit-background-clip: text;
  833. -webkit-text-fill-color: transparent;
  834. background-clip: text;
  835. animation: textShimmer 2s linear infinite;
  836. }
  837. @keyframes textShimmer {
  838. 0% {
  839. background-position: 0% center;
  840. }
  841. 100% {
  842. background-position: 200% center;
  843. }
  844. }
  845. /* AI 图标内部的星星动画 */
  846. @keyframes starPulse {
  847. 0%,
  848. 100% {
  849. transform: scale(1) rotate(0deg);
  850. opacity: 0.9;
  851. }
  852. 50% {
  853. transform: scale(1.15) rotate(15deg);
  854. opacity: 1;
  855. }
  856. }
  857. @keyframes starOrbit {
  858. 0% {
  859. transform: rotate(0deg) translateX(5px) rotate(0deg);
  860. }
  861. 100% {
  862. transform: rotate(360deg) translateX(5px) rotate(-360deg);
  863. }
  864. }
  865. /* 光晕扫描 */
  866. .scan-line {
  867. position: absolute;
  868. top: 0;
  869. left: -100%;
  870. width: 60%;
  871. height: 100%;
  872. background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
  873. animation: scanAnim 2s ease-in-out infinite;
  874. border-radius: 50%;
  875. }
  876. @keyframes scanAnim {
  877. 0% {
  878. left: -60%;
  879. }
  880. 100% {
  881. left: 160%;
  882. }
  883. }
  884. .AISpan {
  885. display: flex;
  886. align-items: center;
  887. color: #1989fa;
  888. margin-right: 5px;
  889. font-size: 12px;
  890. }
  891. .AISpan::before {
  892. content: '';
  893. display: inline-block;
  894. width: 6px;
  895. height: 6px;
  896. border-radius: 50%;
  897. background: #2979ff;
  898. animation: blink 1.2s ease-in-out infinite;
  899. margin-right: 5px;
  900. }
  901. @keyframes blink {
  902. 0%,
  903. 100% {
  904. opacity: 0.3;
  905. }
  906. 50% {
  907. opacity: 1;
  908. }
  909. }
  910. }
  911. </style>