index.vue 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427
  1. <template>
  2. <view class="order-container">
  3. <erp-nav-bar title="ERP 下单" :show-back="false" />
  4. <!-- 0. 全屏加载过渡 -->
  5. <view class="loading-state-full" v-if="isLoading">
  6. <view class="loading-anim-box">
  7. <view class="dot-spinner">
  8. <view class="dot"></view>
  9. <view class="dot"></view>
  10. <view class="dot"></view>
  11. </view>
  12. <text class="loading-text">正在同步 ERP 数据...</text>
  13. </view>
  14. </view>
  15. <!-- 1. 未登录状态 -->
  16. <view class="auth-waiting-full" v-else-if="!isLoggedIn">
  17. <view class="auth-card">
  18. <image class="auth-icon" src="https://img.icons8.com/color/192/hourglass-sand-top.png" mode="aspectFit">
  19. </image>
  20. <text class="auth-title">未登录</text>
  21. <text class="auth-desc">您还未登录账号,请先登录以后在进行下单操作</text>
  22. <button class="contact-btn" @click="goToLogin">前往登录</button>
  23. </view>
  24. </view>
  25. <!-- 2. 已登录但未分配授权客户 -->
  26. <view class="auth-waiting-full" v-else-if="!myInfo.authClientFRowID">
  27. <view class="auth-card">
  28. <image class="auth-icon" src="https://img.icons8.com/color/192/hourglass-sand-top.png" mode="aspectFit">
  29. </image>
  30. <text class="auth-title">待管理员授权</text>
  31. <text class="auth-desc">您的账户尚未获得下单权限,请联系管理员核准授权后即可进行下单操作。</text>
  32. <button class="contact-btn" @click="contactAdmin">联系管理员</button>
  33. </view>
  34. </view>
  35. <!-- 3. 已登录且已分配授权客户:显示下单页面 -->
  36. <template v-else>
  37. <scroll-view scroll-y class="order-scroll-list" :show-scrollbar="false" :enhanced="true">
  38. <view class="list-wrapper">
  39. <!-- 已选客户信息 -->
  40. <view class="client-info-bar" v-if="selectedClientName">
  41. <text class="client-label">下单客户:</text>
  42. <text class="client-name-text">{{ selectedClientName }}</text>
  43. </view>
  44. <!-- 列表头部:仅在有数据时显示 -->
  45. <view class="list-header" v-if="selectedModels.length > 0">
  46. <view class="header-left">
  47. <text class="header-text" v-if="!batchMode">已选型号列表:</text>
  48. <text class="header-text" v-else>批量修改({{ selectedIds.length }}/{{ selectedModels.length
  49. }})</text>
  50. <view class="select-all-toggle" v-if="batchMode" @click="toggleSelectAll">
  51. <text class="select-all-icon" :class="{ checked: isAllSelected }">☐</text>
  52. <text class="select-all-text">{{ isAllSelected ? '取消全选' : '全选' }}</text>
  53. </view>
  54. </view>
  55. <view class="batch-toggle" :class="{ active: batchMode }" @click="toggleBatchMode">
  56. <text>{{ batchMode ? '退出' : '批量修改' }}</text>
  57. </view>
  58. </view>
  59. <!-- 1. 列表渲染 (精品化设计) -->
  60. <view class="model-item-card" v-for="(item, index) in selectedModels" :key="index"
  61. v-if="selectedModels.length > 0"
  62. :class="{ 'batch-mode-card': batchMode, 'batch-selected': batchMode && isSelected(item.rowId) }">
  63. <view class="batch-checkbox" v-if="batchMode" @click.stop="toggleSelect(item.rowId)">
  64. <view class="checkbox-circle" :class="{ checked: isSelected(item.rowId) }">
  65. <text class="check-icon" v-if="isSelected(item.rowId)">✓</text>
  66. </view>
  67. </view>
  68. <view class="card-body" @click="batchMode ? toggleSelect(item.rowId) : editItem(index, item)">
  69. <view class="remove-icon" @click.stop="removeItem(index)">
  70. <text class="x-icon">×</text>
  71. </view>
  72. <view class="card-line">
  73. <view class="model-info">
  74. <text class="model-value">{{ item.modelNum }}</text>
  75. </view>
  76. <view class="count-tag">
  77. 支数<text class="count-num">{{ item.count }}</text>
  78. </view>
  79. </view>
  80. <view class="card-line secondary">
  81. <text class="surface-label">表面名称:</text>
  82. <text class="surface-text">{{ item.surfaceName }}</text>
  83. </view>
  84. </view>
  85. </view>
  86. <!-- 2. 全屏缺省状态:美化后的引导页 -->
  87. <view class="empty-state-full" v-else>
  88. <view class="empty-visual">
  89. <image class="empty-img" src="https://img.icons8.com/clouds/200/shopping-cart.png"
  90. mode="aspectFit"></image>
  91. <view class="empty-bg-glow"></view>
  92. </view>
  93. <text class="empty-title">暂无已选型号</text>
  94. <button class="empty-action-btn" @click="goToAddModel">选型下单</button>
  95. </view>
  96. <view class="bottom-safe-space"></view>
  97. </view>
  98. </scroll-view>
  99. <!-- 悬浮添加按钮 (仅在有数据时且非批量模式显示) -->
  100. <view class="floating-add-btn" @click="goToAddModel" v-if="selectedModels.length > 0 && !batchMode">
  101. <view class="plus-icon"></view>
  102. </view>
  103. <!-- 批量操作栏(批量模式下常驻) -->
  104. <view class="batch-action-bar" v-if="batchMode">
  105. <view class="batch-count" v-if="selectedIds.length > 0">已选 {{ selectedIds.length }} 项</view>
  106. <view class="batch-count placeholder" v-else>请勾选型号</view>
  107. <view class="batch-btns">
  108. <button class="batch-btn surface-btn" :disabled="selectedIds.length === 0"
  109. @click="openBatchSurfacePicker">批量修改表面</button>
  110. <button class="batch-btn pack-btn" :disabled="selectedIds.length === 0"
  111. @click="openBatchPackPicker">批量修改包装</button>
  112. </view>
  113. </view>
  114. <!-- 底部支付/下单汇总栏 (仅在有数据时且非批量模式显示) -->
  115. <view class="footer-summary-bar" v-if="selectedModels.length > 0 && !batchMode">
  116. <view class="summary-info">
  117. <text class="count-label">共计:</text>
  118. <text class="num-highlight">{{ selectedModels.length }}</text>
  119. <text class="unit">条</text>
  120. <view class="split-line"></view>
  121. <text class="num-highlight green">{{ totalCount }}</text>
  122. <text class="unit">支</text>
  123. </view>
  124. <button class="submit-order-btn" :disabled="selectedModels.length === 0"
  125. @click="submitFinalOrder">立即下单</button>
  126. </view>
  127. </template>
  128. <!-- 底部菜单栏 -->
  129. <erp-tab-bar active="order"></erp-tab-bar>
  130. <!-- 批量修改 - 表面处理选择弹层 -->
  131. <view class="custom-picker-mask" v-if="showBatchSurfacePicker" @click="showBatchSurfacePicker = false"
  132. @touchmove.stop.prevent>
  133. <view class="picker-popup" @click.stop>
  134. <view class="popup-header">
  135. <text class="cancel-text" @click="showBatchSurfacePicker = false">取消</text>
  136. <text class="popup-title">选择表面处理</text>
  137. <text class="confirm-text" @click="confirmBatchSurface">确定</text>
  138. </view>
  139. <!-- 搜索栏 -->
  140. <view class="search-bar">
  141. <view class="search-input-wrap">
  142. <text class="search-icon">🔍</text>
  143. <input class="search-input" type="text" v-model="batchSurfaceSearchKey" placeholder="输入名称检索"
  144. @input="onBatchSurfaceSearch" />
  145. </view>
  146. </view>
  147. <!-- 层级面包屑 -->
  148. <view class="breadcrumb-bar" v-if="batchSurfaceLevel > 1">
  149. <text class="back-btn" @click="goBackBatchSurfaceLevel">← 返回</text>
  150. <text class="breadcrumb-path">{{batchSurfaceBreadcrumbs.map(b => b.label).join(' / ')}}</text>
  151. </view>
  152. <!-- 列表区 -->
  153. <scroll-view scroll-y class="item-list">
  154. <view class="option-item kind-item" v-for="(item, index) in batchSurfaceKindList" :key="'bsk'+index"
  155. @click="drillDownBatchSurface(item)">
  156. <text class="option-text kind-text">{{ item.num }} - {{ item.name }}</text>
  157. <text class="arrow-right">›</text>
  158. </view>
  159. <view class="option-item" v-for="item in batchSurfaceItemList" :key="'bsi'+item.rowId"
  160. :class="{ active: batchSurfaceId === item.rowId }">
  161. <text class="option-text" @click="selectBatchSurfaceItem(item)">{{ item.num }} - {{ item.name
  162. }}</text>
  163. </view>
  164. </scroll-view>
  165. </view>
  166. </view>
  167. <!-- 批量修改 - 包装方式选择弹层 -->
  168. <view class="custom-picker-mask" v-if="showBatchPackPicker" @click="showBatchPackPicker = false"
  169. @touchmove.stop.prevent>
  170. <view class="picker-popup" @click.stop>
  171. <view class="popup-header">
  172. <text class="cancel-text" @click="showBatchPackPicker = false">取消</text>
  173. <text class="popup-title">选择包装方式</text>
  174. <text class="confirm-text" @click="confirmBatchPack">确定</text>
  175. </view>
  176. <view class="search-bar">
  177. <view class="search-input-wrap">
  178. <text class="search-icon">🔍</text>
  179. <input class="search-input" type="text" v-model="batchPackSearchKey" placeholder="输入名称检索"
  180. @input="onBatchPackSearch" />
  181. </view>
  182. </view>
  183. <scroll-view scroll-y class="item-list" @scrolltolower="loadMorePackBatch">
  184. <view class="option-item" v-for="item in batchPackList" :key="item.rowId"
  185. :class="{ active: batchPackId === item.rowId }"
  186. @click="batchPackId = item.rowId; batchPackName = item.name">
  187. <text>{{ item.num }} - {{ item.name }}</text>
  188. <icon type="success_no_circle" size="16" color="#C1001C" v-if="batchPackId === item.rowId">
  189. </icon>
  190. </view>
  191. </scroll-view>
  192. </view>
  193. </view>
  194. <order-confirm-popup :visible="showConfirmPopup" :models="selectedModels" :clientName="confirmClientName"
  195. :submitting="confirmSubmitting" @confirm="handleConfirmOrder" @close="showConfirmPopup = false" />
  196. </view>
  197. </template>
  198. <script>
  199. import ErpTabBar from '@/components/erp-tab-bar.vue';
  200. import ErpNavBar from '@/components/erp-nav-bar.vue';
  201. import OrderConfirmPopup from './components/order-confirm-popup.vue';
  202. import { getMyInfo } from '@/api/system/customer.js';
  203. import { listOrderDetail, batchUpdateOrderDetail } from '@/api/erp/orderDetail.js';
  204. import { listColor } from '@/api/erp/color.js';
  205. import { listColorKind } from '@/api/erp/colorKind.js';
  206. import { listPagePack } from '@/api/erp/pack.js';
  207. import { addOrder } from '@/api/erp/order.js';
  208. export default {
  209. components: { ErpNavBar, ErpTabBar, OrderConfirmPopup },
  210. data() {
  211. return {
  212. isLoggedIn: false,
  213. isLoading: true, // 初始为加载中
  214. myInfo: {},
  215. selectedModels: [],
  216. selectedClientId: '',
  217. selectedClientName: '',
  218. // 批量修改相关
  219. batchMode: false,
  220. selectedIds: [],
  221. // 表面处理选择器
  222. showBatchSurfacePicker: false,
  223. batchSurfaceId: '',
  224. batchSurfaceName: '',
  225. batchSurfaceSearchKey: '',
  226. batchSurfaceBreadcrumbs: [],
  227. batchSurfaceLevel: 1,
  228. batchSurfaceKindList: [],
  229. batchSurfaceItemList: [],
  230. // 包装方式选择器
  231. showBatchPackPicker: false,
  232. batchPackList: [],
  233. batchPackPageNum: 1,
  234. batchPackHasMore: true,
  235. batchPackLoading: false,
  236. batchPackId: '',
  237. batchPackName: '',
  238. batchPackSearchKey: '',
  239. batchPackSearchTimer: null,
  240. showConfirmPopup: false,
  241. confirmClientId: '',
  242. confirmClientName: '',
  243. confirmSubmitting: false
  244. }
  245. },
  246. computed: {
  247. totalCount() {
  248. return this.selectedModels.reduce((sum, item) => sum + parseInt(item.count || 0), 0);
  249. },
  250. isAllSelected() {
  251. return this.selectedModels.length > 0 && this.selectedIds.length === this.selectedModels.length;
  252. }
  253. },
  254. onLoad() {
  255. // 监听添加型号的事件 - 重新从后端加载
  256. uni.$on('add_order_item', (data) => {
  257. this.loadOrderItems(false); // 添加时静默加载,不显示全屏动画
  258. });
  259. // 监听修改型号的事件 - 重新从后端加载
  260. uni.$on('update_order_item', (res) => {
  261. this.loadOrderItems(false);
  262. });
  263. },
  264. onShow() {
  265. this.checkLoginStatus();
  266. },
  267. onUnload() {
  268. uni.$off('add_order_item');
  269. uni.$off('update_order_item');
  270. },
  271. methods: {
  272. /**
  273. * 加载已选型号列表(OrderID 为空的草稿)
  274. * @Author: Antigravity
  275. */
  276. async loadOrderItems(showFullLoading = true) {
  277. if (showFullLoading) this.isLoading = true;
  278. try {
  279. const res = await listOrderDetail({ orderId: '' });
  280. this.selectedModels = res.data || [];
  281. } catch (e) {
  282. console.error('加载型号列表失败', e);
  283. uni.showToast({ title: e || '加载型号列表失败', icon: 'none' });
  284. } finally {
  285. this.isLoading = false;
  286. }
  287. },
  288. async checkLoginStatus() {
  289. const token = uni.getStorageSync('token');
  290. if (!token) {
  291. this.isLoggedIn = false;
  292. this.myInfo = {};
  293. this.selectedClientId = '';
  294. this.selectedClientName = '';
  295. this.isLoading = false;
  296. return;
  297. }
  298. try {
  299. const res = await getMyInfo();
  300. this.isLoggedIn = true;
  301. this.myInfo = res.data || {};
  302. this.loadOrderItems();
  303. } catch (e) {
  304. uni.showToast({ title: e || '登录状态校验失败', icon: 'none' });
  305. uni.removeStorageSync('token');
  306. uni.removeStorageSync('isLogin');
  307. this.isLoggedIn = false;
  308. this.myInfo = {};
  309. this.selectedClientId = '';
  310. this.selectedClientName = '';
  311. this.isLoading = false;
  312. }
  313. },
  314. goToLogin() {
  315. uni.reLaunch({ url: '/pages/login/index' });
  316. },
  317. contactAdmin() { uni.showModal({ title: '联系管理员', content: '管理员电话:138-0000-0000', showCancel: false, confirmColor: '#C1001C' }); },
  318. goToAddModel() {
  319. uni.navigateTo({
  320. url: '/pages/order/add-model/index'
  321. });
  322. },
  323. editItem(index, item) {
  324. uni.navigateTo({
  325. url: `/pages/order/edit-model/index?index=${index}&data=${encodeURIComponent(JSON.stringify(item))}`
  326. });
  327. },
  328. removeItem(index) {
  329. const self = this;
  330. uni.showModal({
  331. title: '提示',
  332. content: '确定移除该型号吗?',
  333. success: (res) => {
  334. if (res.confirm) {
  335. self.selectedModels.splice(index, 1);
  336. }
  337. }
  338. });
  339. },
  340. /**
  341. * 切换全选 / 取消全选
  342. * @Author: Trae
  343. */
  344. toggleSelectAll() {
  345. if (this.isAllSelected) {
  346. this.selectedIds = [];
  347. } else {
  348. this.selectedIds = this.selectedModels.map(item => item.rowId);
  349. }
  350. },
  351. /**
  352. * 切换批量修改模式
  353. * @Author: Trae
  354. */
  355. toggleBatchMode() {
  356. this.batchMode = !this.batchMode;
  357. if (!this.batchMode) {
  358. this.selectedIds = [];
  359. }
  360. },
  361. /**
  362. * 切换选中状态
  363. * @Author: Trae
  364. */
  365. toggleSelect(rowId) {
  366. const idx = this.selectedIds.indexOf(rowId);
  367. if (idx > -1) {
  368. this.selectedIds.splice(idx, 1);
  369. } else {
  370. this.selectedIds.push(rowId);
  371. }
  372. },
  373. /**
  374. * 判断是否已选中
  375. * @Author: Trae
  376. */
  377. isSelected(rowId) {
  378. return this.selectedIds.indexOf(rowId) > -1;
  379. },
  380. /**
  381. * 打开批量修改表面处理选择器(二级级联)
  382. * @Author: Trae
  383. */
  384. openBatchSurfacePicker() {
  385. if (this.selectedIds.length === 0) {
  386. uni.showToast({ title: '请先选择型号', icon: 'none' });
  387. return;
  388. }
  389. this.showBatchSurfacePicker = true;
  390. this.batchSurfaceId = '';
  391. this.batchSurfaceName = '';
  392. this.batchSurfaceSearchKey = '';
  393. this.batchSurfaceLevel = 1;
  394. this.batchSurfaceBreadcrumbs = [];
  395. this.loadBatchSurfaceList('');
  396. },
  397. /**
  398. * 加载表面处理系列,点击系列后同时加载子系列和具体颜色(批量选择器)
  399. * @Author: Trae
  400. */
  401. async loadBatchSurfaceList(parentRowId) {
  402. try {
  403. const keyword = (this.batchSurfaceSearchKey || '').trim();
  404. const kindParams = { name: keyword || undefined };
  405. if (parentRowId) {
  406. kindParams.parentRowId = parentRowId;
  407. }
  408. const kindRes = await listColorKind(kindParams);
  409. this.batchSurfaceKindList = kindRes.data || [];
  410. if (parentRowId) {
  411. const colorParams = { name: keyword || undefined, parentRowId };
  412. const colorRes = await listColor(colorParams);
  413. this.batchSurfaceItemList = colorRes.data || [];
  414. } else {
  415. this.batchSurfaceItemList = [];
  416. }
  417. } catch (e) {
  418. uni.showToast({ title: e || '加载表面处理失败', icon: 'none' });
  419. }
  420. },
  421. /**
  422. * 表面处理搜索
  423. * @Author: Trae
  424. */
  425. onBatchSurfaceSearch() {
  426. const parentRowId = this.batchSurfaceBreadcrumbs.length > 0
  427. ? this.batchSurfaceBreadcrumbs[this.batchSurfaceBreadcrumbs.length - 1].rowId : '';
  428. this.loadBatchSurfaceList(parentRowId);
  429. },
  430. selectBatchSurfaceItem(item) {
  431. this.batchSurfaceId = item.rowId;
  432. this.batchSurfaceName = item.name;
  433. },
  434. drillDownBatchSurface(item) {
  435. this.batchSurfaceBreadcrumbs.push({ rowId: item.rowId, label: item.num });
  436. this.batchSurfaceId = '';
  437. this.batchSurfaceName = '';
  438. this.batchSurfaceLevel++;
  439. this.loadBatchSurfaceList(item.rowId);
  440. },
  441. goBackBatchSurfaceLevel() {
  442. this.batchSurfaceBreadcrumbs.pop();
  443. this.batchSurfaceLevel--;
  444. this.batchSurfaceId = '';
  445. this.batchSurfaceName = '';
  446. const parentRowId = this.batchSurfaceBreadcrumbs.length > 0
  447. ? this.batchSurfaceBreadcrumbs[this.batchSurfaceBreadcrumbs.length - 1].rowId : '';
  448. this.loadBatchSurfaceList(parentRowId);
  449. },
  450. /**
  451. * 确认批量修改表面处理
  452. * @Author: Trae
  453. */
  454. async confirmBatchSurface() {
  455. if (!this.batchSurfaceId) {
  456. uni.showToast({ title: '请选择表面处理', icon: 'none' });
  457. return;
  458. }
  459. this.showBatchSurfacePicker = false;
  460. uni.showLoading({ title: '修改中...', mask: true });
  461. try {
  462. await batchUpdateOrderDetail({
  463. rowIds: this.selectedIds,
  464. surfaceId: this.batchSurfaceId,
  465. surfaceName: this.batchSurfaceName
  466. });
  467. uni.hideLoading();
  468. uni.showToast({ title: '修改成功', icon: 'success' });
  469. this.selectedIds = [];
  470. this.loadOrderItems(false);
  471. } catch (e) {
  472. uni.hideLoading();
  473. uni.showToast({ title: e || '修改失败', icon: 'none' });
  474. }
  475. this.batchSurfaceLevel = 1;
  476. this.batchSurfaceBreadcrumbs = [];
  477. this.batchSurfaceId = '';
  478. this.batchSurfaceName = '';
  479. },
  480. /**
  481. * 打开批量修改包装方式选择器
  482. * @Author: Trae
  483. */
  484. openBatchPackPicker() {
  485. if (this.selectedIds.length === 0) {
  486. uni.showToast({ title: '请先选择型号', icon: 'none' });
  487. return;
  488. }
  489. this.showBatchPackPicker = true;
  490. this.batchPackId = '';
  491. this.batchPackName = '';
  492. this.batchPackSearchKey = '';
  493. this.batchPackPageNum = 1;
  494. if (this.batchPackList.length === 0) {
  495. this.loadBatchPackList();
  496. }
  497. },
  498. /**
  499. * 加载包装方式列表(批量选择器)
  500. * @Author: Trae
  501. */
  502. async loadBatchPackList(pageNum = 1, keyword = '') {
  503. if (this.batchPackLoading) return;
  504. this.batchPackLoading = true;
  505. try {
  506. const res = await listPagePack({
  507. pageNum,
  508. pageSize: 10,
  509. name: keyword || undefined
  510. });
  511. const rows = res.rows || [];
  512. if (pageNum === 1) {
  513. this.batchPackList = rows;
  514. } else {
  515. this.batchPackList = [...this.batchPackList, ...rows];
  516. }
  517. this.batchPackHasMore = rows.length >= 20;
  518. } catch (e) {
  519. uni.showToast({ title: e || '加载包装方式失败', icon: 'none' });
  520. } finally {
  521. this.batchPackLoading = false;
  522. }
  523. },
  524. /**
  525. * 加载更多包装方式列表
  526. * @Author: Trae
  527. */
  528. loadMorePackBatch() {
  529. if (!this.batchPackHasMore || this.batchPackLoading) return;
  530. this.batchPackPageNum++;
  531. this.loadBatchPackList(this.batchPackPageNum, this.batchPackSearchKey);
  532. },
  533. /**
  534. * 包装方式搜索(防抖)
  535. * @Author: Trae
  536. */
  537. onBatchPackSearch() {
  538. if (this.batchPackSearchTimer) clearTimeout(this.batchPackSearchTimer);
  539. this.batchPackSearchTimer = setTimeout(() => {
  540. this.batchPackPageNum = 1;
  541. this.loadBatchPackList(1, this.batchPackSearchKey);
  542. }, 300);
  543. },
  544. /**
  545. * 确认批量修改包装方式
  546. * @Author: Trae
  547. */
  548. async confirmBatchPack() {
  549. if (!this.batchPackId) {
  550. uni.showToast({ title: '请选择包装方式', icon: 'none' });
  551. return;
  552. }
  553. this.showBatchPackPicker = false;
  554. uni.showLoading({ title: '修改中...', mask: true });
  555. try {
  556. await batchUpdateOrderDetail({
  557. rowIds: this.selectedIds,
  558. packId: this.batchPackId,
  559. packName: this.batchPackName
  560. });
  561. uni.hideLoading();
  562. uni.showToast({ title: '修改成功', icon: 'success' });
  563. this.selectedIds = [];
  564. this.loadOrderItems(false);
  565. } catch (e) {
  566. uni.hideLoading();
  567. uni.showToast({ title: e || '修改失败', icon: 'none' });
  568. }
  569. },
  570. /**
  571. * 提交最终订单 - 选择客户后弹出确认弹窗
  572. * @Author: Antigravity
  573. */
  574. async submitFinalOrder() {
  575. if (this.selectedModels.length === 0) return;
  576. const clientList = this.myInfo.authClientList || [];
  577. if (clientList.length === 0) {
  578. uni.showToast({ title: '暂无授权客户,无法下单', icon: 'none' });
  579. return;
  580. }
  581. // 单个授权客户:直接弹出
  582. if (clientList.length === 1) {
  583. this.confirmClientId = clientList[0].rowId;
  584. this.confirmClientName = clientList[0].name;
  585. this.showConfirmPopup = true;
  586. return;
  587. }
  588. // 多个授权客户:先选择再弹出
  589. const clientNames = clientList.map(c => c.name);
  590. const res = await new Promise((resolve) => {
  591. uni.showActionSheet({
  592. itemList: clientNames,
  593. success: (r) => resolve(r),
  594. fail: () => resolve(null)
  595. });
  596. });
  597. if (res && res.tapIndex !== undefined) {
  598. const chosen = clientList[res.tapIndex];
  599. this.confirmClientId = chosen.rowId;
  600. this.confirmClientName = chosen.name;
  601. this.showConfirmPopup = true;
  602. }
  603. },
  604. /**
  605. * 确认弹窗回调 - 正式执行下单
  606. * @Author: Trae
  607. */
  608. async handleConfirmOrder() {
  609. this.confirmSubmitting = true;
  610. uni.showLoading({ title: '正在提交订单', mask: true });
  611. try {
  612. const detailIds = this.selectedModels.map(item => item.rowId);
  613. const submitRes = await addOrder({
  614. detailIds,
  615. clientId: this.confirmClientId,
  616. clientName: this.confirmClientName
  617. });
  618. uni.hideLoading();
  619. this.confirmSubmitting = false;
  620. this.showConfirmPopup = false;
  621. const orderId = submitRes.data;
  622. uni.showToast({ title: '下单成功', icon: 'success' });
  623. setTimeout(() => {
  624. uni.navigateTo({
  625. url: '/pages/order/success/index?orderId=' + orderId
  626. });
  627. }, 1500);
  628. } catch (e) {
  629. uni.hideLoading();
  630. this.confirmSubmitting = false;
  631. uni.showToast({ title: e || '下单失败', icon: 'none' });
  632. }
  633. }
  634. }
  635. }
  636. </script>
  637. <style scoped>
  638. /deep/ ::-webkit-scrollbar {
  639. display: none !important;
  640. width: 0 !important;
  641. height: 0 !important;
  642. }
  643. .order-container {
  644. width: 100%;
  645. height: 100vh;
  646. background: #f8fafc;
  647. display: flex;
  648. flex-direction: column;
  649. overflow: hidden;
  650. }
  651. /* 授权等待样式保持一致 */
  652. .auth-waiting-full {
  653. flex: 1;
  654. display: flex;
  655. flex-direction: column;
  656. align-items: center;
  657. justify-content: flex-start;
  658. padding: 200rpx 40rpx 40rpx;
  659. background: linear-gradient(180deg, rgba(0, 122, 255, 0.08) 0%, rgba(247, 248, 250, 1) 100%);
  660. }
  661. .auth-card {
  662. display: flex;
  663. flex-direction: column;
  664. align-items: center;
  665. text-align: center;
  666. }
  667. .auth-icon {
  668. width: 200rpx;
  669. height: 200rpx;
  670. margin-bottom: 50rpx;
  671. }
  672. .auth-title {
  673. font-size: 44rpx;
  674. font-weight: bold;
  675. color: #1a1a1a;
  676. margin-bottom: 24rpx;
  677. }
  678. .auth-desc {
  679. font-size: 28rpx;
  680. color: #666;
  681. line-height: 1.8;
  682. margin-bottom: 80rpx;
  683. padding: 0 20rpx;
  684. }
  685. .contact-btn {
  686. width: 360rpx;
  687. height: 96rpx;
  688. background: linear-gradient(135deg, #C1001C 0%, #FF4D4F 100%);
  689. color: #fff;
  690. border-radius: 48rpx;
  691. display: flex;
  692. align-items: center;
  693. justify-content: center;
  694. font-size: 32rpx;
  695. font-weight: bold;
  696. border: none;
  697. box-shadow: 0 12rpx 30rpx rgba(193, 0, 28, 0.2);
  698. }
  699. .authorized-btn {
  700. width: 360rpx;
  701. height: 96rpx;
  702. background: #fff;
  703. color: #C1001C;
  704. border-radius: 48rpx;
  705. display: flex;
  706. align-items: center;
  707. justify-content: center;
  708. font-size: 32rpx;
  709. font-weight: bold;
  710. border: 2rpx solid #C1001C;
  711. margin-top: 30rpx;
  712. }
  713. /* 已授权列表页样式 */
  714. .order-container {
  715. width: 100%;
  716. height: 100vh;
  717. background: #f7f8fa;
  718. display: flex;
  719. flex-direction: column;
  720. overflow: hidden;
  721. }
  722. .order-scroll-list {
  723. flex: 1;
  724. height: 0;
  725. }
  726. .list-wrapper {
  727. padding: 30rpx;
  728. /* 确保最后一条数据不被底部双层固定栏遮挡:汇总栏130 + 菜单栏110 + 安全区 + 缓冲余量 */
  729. padding-bottom: calc(280rpx + env(safe-area-inset-bottom));
  730. }
  731. .list-header {
  732. padding: 10rpx 0 20rpx;
  733. display: flex;
  734. align-items: center;
  735. justify-content: space-between;
  736. flex-wrap: wrap;
  737. gap: 10rpx;
  738. }
  739. .header-left {
  740. display: flex;
  741. align-items: center;
  742. gap: 16rpx;
  743. }
  744. .header-text {
  745. font-size: 34rpx;
  746. font-weight: bold;
  747. color: #1a1a1a;
  748. position: relative;
  749. padding-left: 24rpx;
  750. }
  751. .header-text::before {
  752. content: '';
  753. position: absolute;
  754. left: 0;
  755. top: 10%;
  756. height: 80%;
  757. width: 8rpx;
  758. background: #C1001C;
  759. border-radius: 4rpx;
  760. }
  761. .select-all-toggle {
  762. display: flex;
  763. align-items: center;
  764. gap: 6rpx;
  765. padding: 6rpx 16rpx;
  766. background: #f5f5f5;
  767. border-radius: 20rpx;
  768. }
  769. .select-all-icon {
  770. font-size: 28rpx;
  771. color: #999;
  772. }
  773. .select-all-icon.checked {
  774. color: #C1001C;
  775. }
  776. .select-all-text {
  777. font-size: 22rpx;
  778. color: #666;
  779. }
  780. /* 型号卡片:大幅升级美化 */
  781. .model-item-card {
  782. background: #fff;
  783. border-radius: 24rpx;
  784. padding: 36rpx;
  785. margin-bottom: 30rpx;
  786. position: relative;
  787. box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.04);
  788. border: 1rpx solid rgba(0, 0, 0, 0.02);
  789. display: flex;
  790. align-items: stretch;
  791. transition: border 0.25s, background 0.25s, transform 0.15s;
  792. }
  793. .model-item-card.batch-mode-card {
  794. padding-left: 20rpx;
  795. gap: 16rpx;
  796. }
  797. .batch-checkbox {
  798. display: flex;
  799. align-items: center;
  800. justify-content: center;
  801. padding-top: 6rpx;
  802. flex-shrink: 0;
  803. }
  804. .checkbox-circle {
  805. width: 44rpx;
  806. height: 44rpx;
  807. border-radius: 50%;
  808. border: 2rpx solid #ddd;
  809. display: flex;
  810. align-items: center;
  811. justify-content: center;
  812. background: #fff;
  813. transition: all 0.2s;
  814. }
  815. .checkbox-circle.checked {
  816. background: #C1001C;
  817. border-color: #C1001C;
  818. }
  819. .check-icon {
  820. font-size: 26rpx;
  821. color: #fff;
  822. font-weight: bold;
  823. }
  824. .card-body {
  825. flex: 1;
  826. min-width: 0;
  827. position: relative;
  828. }
  829. .remove-icon {
  830. position: absolute;
  831. right: -36rpx;
  832. top: -36rpx;
  833. width: 50rpx;
  834. height: 50rpx;
  835. background: rgba(255, 77, 79, 0.1);
  836. border-radius: 0 24rpx 0 24rpx;
  837. display: flex;
  838. align-items: center;
  839. justify-content: center;
  840. z-index: 5;
  841. }
  842. .x-icon {
  843. font-size: 32rpx;
  844. color: #ff4d4f;
  845. font-weight: bold;
  846. }
  847. .card-line {
  848. display: flex;
  849. align-items: center;
  850. margin-bottom: 20rpx;
  851. }
  852. .card-line.secondary {
  853. margin-bottom: 0;
  854. padding-top: 20rpx;
  855. border-top: 1rpx dashed #f0f0f0;
  856. }
  857. .model-value {
  858. font-size: 34rpx;
  859. font-weight: bold;
  860. color: #333;
  861. flex: 1;
  862. }
  863. .count-tag {
  864. background: #FFF1F2;
  865. color: #C1001C;
  866. padding: 4rpx 16rpx;
  867. border-radius: 8rpx;
  868. font-size: 24rpx;
  869. font-weight: bold;
  870. }
  871. .count-num {
  872. font-size: 30rpx;
  873. margin-left: 8rpx;
  874. }
  875. .surface-label {
  876. font-size: 26rpx;
  877. color: #999;
  878. }
  879. .surface-text {
  880. font-size: 28rpx;
  881. color: #666;
  882. }
  883. /* 悬浮添加按钮:位置上移避免拥挤 */
  884. .floating-add-btn {
  885. position: fixed;
  886. right: 40rpx;
  887. bottom: calc(260rpx + env(safe-area-inset-bottom) + 40rpx);
  888. width: 110rpx;
  889. height: 110rpx;
  890. background: #C1001C;
  891. border-radius: 50%;
  892. display: flex;
  893. align-items: center;
  894. justify-content: center;
  895. box-shadow: 0 12rpx 40rpx rgba(193, 0, 28, 0.4);
  896. z-index: 100;
  897. transition: transform 0.2s;
  898. }
  899. .floating-add-btn:active {
  900. transform: scale(0.9);
  901. }
  902. .plus-icon {
  903. width: 40rpx;
  904. height: 4rpx;
  905. background: #fff;
  906. border-radius: 2rpx;
  907. position: relative;
  908. }
  909. .plus-icon::after {
  910. content: '';
  911. position: absolute;
  912. top: 0;
  913. left: 0;
  914. width: 100%;
  915. height: 100%;
  916. background: #fff;
  917. transform: rotate(90deg);
  918. border-radius: 2rpx;
  919. }
  920. /* 底部汇总栏:微调间距与样式 */
  921. .footer-summary-bar {
  922. position: fixed;
  923. bottom: calc(110rpx + env(safe-area-inset-bottom));
  924. left: 0;
  925. width: 100%;
  926. height: 130rpx;
  927. background: #fff;
  928. border-top: 1rpx solid #f0f0f0;
  929. display: flex;
  930. align-items: center;
  931. justify-content: space-between;
  932. padding: 0 40rpx;
  933. box-sizing: border-box;
  934. z-index: 99;
  935. box-shadow: 0 -10rpx 40rpx rgba(0, 0, 0, 0.05);
  936. }
  937. .summary-info {
  938. display: flex;
  939. align-items: center;
  940. }
  941. .count-label {
  942. font-size: 26rpx;
  943. color: #999;
  944. }
  945. .num-highlight {
  946. font-size: 36rpx;
  947. font-weight: bold;
  948. color: #1a1a1a;
  949. margin: 0 4rpx;
  950. }
  951. .num-highlight.green {
  952. color: #C1001C;
  953. }
  954. .unit {
  955. font-size: 24rpx;
  956. color: #999;
  957. margin-left: 2rpx;
  958. }
  959. .split-line {
  960. width: 1rpx;
  961. height: 30rpx;
  962. background: #eee;
  963. margin: 0 20rpx;
  964. }
  965. .submit-order-btn {
  966. width: 220rpx;
  967. height: 80rpx;
  968. background: #e0e0e0;
  969. color: #666;
  970. font-size: 28rpx;
  971. border-radius: 40rpx;
  972. display: flex;
  973. align-items: center;
  974. justify-content: center;
  975. border: none;
  976. margin: 0;
  977. transition: all 0.3s;
  978. }
  979. .submit-order-btn:not([disabled]) {
  980. background: #C1001C;
  981. color: #fff;
  982. font-weight: bold;
  983. }
  984. /* 全屏缺省页样式 */
  985. .empty-state-full {
  986. display: flex;
  987. flex-direction: column;
  988. align-items: center;
  989. justify-content: center;
  990. padding-top: 120rpx;
  991. }
  992. .empty-visual {
  993. position: relative;
  994. margin-bottom: 40rpx;
  995. width: 400rpx;
  996. height: 400rpx;
  997. display: flex;
  998. align-items: center;
  999. justify-content: center;
  1000. }
  1001. .empty-img {
  1002. width: 320rpx;
  1003. height: 320rpx;
  1004. z-index: 2;
  1005. }
  1006. .empty-bg-glow {
  1007. position: absolute;
  1008. width: 240rpx;
  1009. height: 240rpx;
  1010. background: radial-gradient(circle, rgba(193, 0, 28, 0.15) 0%, rgba(248, 250, 252, 0) 70%);
  1011. z-index: 1;
  1012. border-radius: 50%;
  1013. }
  1014. .empty-title {
  1015. font-size: 36rpx;
  1016. font-weight: bold;
  1017. color: #1a1a1a;
  1018. margin-bottom: 80rpx;
  1019. }
  1020. .empty-desc {
  1021. font-size: 26rpx;
  1022. color: #999;
  1023. margin-bottom: 60rpx;
  1024. text-align: center;
  1025. padding: 0 80rpx;
  1026. line-height: 1.6;
  1027. }
  1028. .empty-action-btn {
  1029. width: 320rpx;
  1030. height: 90rpx;
  1031. background: #C1001C;
  1032. color: #fff;
  1033. border-radius: 45rpx;
  1034. font-size: 30rpx;
  1035. font-weight: bold;
  1036. display: flex;
  1037. align-items: center;
  1038. justify-content: center;
  1039. box-shadow: 0 10rpx 30rpx rgba(193, 0, 28, 0.2);
  1040. border: none;
  1041. }
  1042. .empty-action-btn:active {
  1043. opacity: 0.8;
  1044. transform: scale(0.96);
  1045. }
  1046. .bottom-safe-space {
  1047. height: 100rpx;
  1048. }
  1049. /* 加载动画样式 */
  1050. .loading-state-full {
  1051. flex: 1;
  1052. display: flex;
  1053. align-items: center;
  1054. justify-content: center;
  1055. padding-bottom: 200rpx;
  1056. }
  1057. .loading-anim-box {
  1058. display: flex;
  1059. flex-direction: column;
  1060. align-items: center;
  1061. }
  1062. .dot-spinner {
  1063. display: flex;
  1064. justify-content: center;
  1065. align-items: center;
  1066. margin-bottom: 30rpx;
  1067. }
  1068. .dot {
  1069. width: 16rpx;
  1070. height: 16rpx;
  1071. background-color: #C1001C;
  1072. border-radius: 50%;
  1073. margin: 0 8rpx;
  1074. animation: dot-pulse 1.4s infinite ease-in-out both;
  1075. }
  1076. .dot:nth-child(1) {
  1077. animation-delay: -0.32s;
  1078. }
  1079. .dot:nth-child(2) {
  1080. animation-delay: -0.16s;
  1081. }
  1082. @keyframes dot-pulse {
  1083. 0%,
  1084. 80%,
  1085. 100% {
  1086. transform: scale(0);
  1087. opacity: 0.3;
  1088. }
  1089. 40% {
  1090. transform: scale(1);
  1091. opacity: 1;
  1092. }
  1093. }
  1094. .loading-text {
  1095. font-size: 26rpx;
  1096. color: #999;
  1097. letter-spacing: 2rpx;
  1098. }
  1099. /* 已选客户信息栏 */
  1100. .client-info-bar {
  1101. display: flex;
  1102. align-items: center;
  1103. padding: 24rpx 32rpx;
  1104. margin-bottom: 20rpx;
  1105. background: linear-gradient(135deg, #FFF1F2 0%, #FFFFFF 100%);
  1106. border-radius: 16rpx;
  1107. border: 1rpx solid rgba(193, 0, 28, 0.1);
  1108. }
  1109. .client-label {
  1110. font-size: 26rpx;
  1111. color: #999;
  1112. }
  1113. .client-name-text {
  1114. font-size: 30rpx;
  1115. font-weight: bold;
  1116. color: #C1001C;
  1117. }
  1118. /* 批量修改按钮 */
  1119. .batch-toggle {
  1120. flex-shrink: 0;
  1121. padding: 8rpx 24rpx;
  1122. background: #C1001C;
  1123. border-radius: 40rpx;
  1124. font-size: 24rpx;
  1125. color: #fff;
  1126. display: flex;
  1127. align-items: center;
  1128. }
  1129. .batch-selected {
  1130. border-color: #C1001C !important;
  1131. background: #FFF1F2 !important;
  1132. }
  1133. /* 批量操作栏 */
  1134. .batch-action-bar {
  1135. position: fixed;
  1136. bottom: calc(110rpx + env(safe-area-inset-bottom));
  1137. left: 0;
  1138. width: 100%;
  1139. height: 110rpx;
  1140. background: #fff;
  1141. border-top: 1rpx solid #f0f0f0;
  1142. display: flex;
  1143. align-items: center;
  1144. justify-content: space-between;
  1145. padding: 0 30rpx;
  1146. box-sizing: border-box;
  1147. z-index: 100;
  1148. box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
  1149. }
  1150. .batch-count {
  1151. font-size: 28rpx;
  1152. color: #333;
  1153. font-weight: 500;
  1154. }
  1155. .batch-count.placeholder {
  1156. color: #ccc;
  1157. }
  1158. .batch-btns {
  1159. display: flex;
  1160. gap: 16rpx;
  1161. }
  1162. .batch-btn {
  1163. width: auto;
  1164. height: 64rpx;
  1165. padding: 0 28rpx;
  1166. border-radius: 32rpx;
  1167. font-size: 26rpx;
  1168. font-weight: 500;
  1169. display: flex;
  1170. align-items: center;
  1171. border: none;
  1172. line-height: 64rpx;
  1173. transition: opacity 0.2s;
  1174. }
  1175. .batch-btn[disabled] {
  1176. opacity: 0.4;
  1177. }
  1178. .surface-btn {
  1179. background: linear-gradient(135deg, #1890FF, #096DD9);
  1180. color: #fff;
  1181. }
  1182. .pack-btn {
  1183. background: linear-gradient(135deg, #52C41A, #389E0D);
  1184. color: #fff;
  1185. }
  1186. /* 选择器弹层(参照 edit-model 模式) */
  1187. .custom-picker-mask {
  1188. position: fixed;
  1189. top: 0;
  1190. left: 0;
  1191. right: 0;
  1192. bottom: 0;
  1193. background: rgba(0, 0, 0, 0.4);
  1194. z-index: 1000;
  1195. display: flex;
  1196. align-items: flex-end;
  1197. }
  1198. .picker-popup {
  1199. width: 100%;
  1200. background: #fff;
  1201. border-radius: 32rpx 32rpx 0 0;
  1202. padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
  1203. animation: slideUp 0.15s ease-out;
  1204. }
  1205. @keyframes slideUp {
  1206. from {
  1207. transform: translateY(100%);
  1208. }
  1209. to {
  1210. transform: translateY(0);
  1211. }
  1212. }
  1213. .popup-header {
  1214. display: flex;
  1215. justify-content: space-between;
  1216. align-items: center;
  1217. padding: 30rpx 40rpx;
  1218. border-bottom: 1rpx solid #f0f0f0;
  1219. }
  1220. .popup-title {
  1221. font-size: 32rpx;
  1222. font-weight: bold;
  1223. color: #333;
  1224. }
  1225. .cancel-text,
  1226. .confirm-text {
  1227. font-size: 30rpx;
  1228. padding: 10rpx;
  1229. }
  1230. .confirm-text {
  1231. color: #C1001C;
  1232. font-weight: bold;
  1233. }
  1234. .item-list {
  1235. max-height: 50vh;
  1236. padding: 0 40rpx;
  1237. }
  1238. .option-item {
  1239. height: 110rpx;
  1240. display: flex;
  1241. align-items: center;
  1242. justify-content: space-between;
  1243. border-bottom: 1rpx solid #f8f8f8;
  1244. font-size: 32rpx;
  1245. color: #333;
  1246. }
  1247. .option-item.active {
  1248. color: #C1001C;
  1249. font-weight: bold;
  1250. }
  1251. .kind-item {
  1252. background: #fafbfc;
  1253. }
  1254. .kind-text {
  1255. color: #556;
  1256. }
  1257. .option-text {
  1258. flex: 1;
  1259. padding: 10rpx 0;
  1260. }
  1261. .arrow-right {
  1262. font-size: 56rpx;
  1263. color: #bbb;
  1264. padding: 10rpx 0 10rpx 20rpx;
  1265. font-weight: 300;
  1266. }
  1267. /* 级联面包屑 */
  1268. .breadcrumb-bar {
  1269. display: flex;
  1270. align-items: center;
  1271. padding: 16rpx 40rpx;
  1272. background: #fafafa;
  1273. border-bottom: 1rpx solid #f0f0f0;
  1274. }
  1275. .back-btn {
  1276. color: #C1001C;
  1277. font-size: 28rpx;
  1278. margin-right: 16rpx;
  1279. }
  1280. .breadcrumb-path {
  1281. font-size: 28rpx;
  1282. color: #666;
  1283. }
  1284. /* 搜索栏样式 */
  1285. .search-bar {
  1286. padding: 16rpx 40rpx;
  1287. border-bottom: 1rpx solid #f0f0f0;
  1288. }
  1289. .search-input-wrap {
  1290. display: flex;
  1291. align-items: center;
  1292. background: #f5f6f8;
  1293. border-radius: 32rpx;
  1294. padding: 12rpx 24rpx;
  1295. }
  1296. .search-icon {
  1297. font-size: 28rpx;
  1298. margin-right: 12rpx;
  1299. }
  1300. .search-input {
  1301. flex: 1;
  1302. font-size: 26rpx;
  1303. color: #333;
  1304. height: 56rpx;
  1305. }
  1306. </style>