index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <template>
  2. <view class="order-detail-container">
  3. <!-- 顶部导航栏 -->
  4. <u-navbar :autoBack="true" :placeholder="true" v-hideNav>
  5. <template slot="center">
  6. <view class="navbar-center">
  7. <text class="navbar-item" @click="handleBrandClick">{{ topInfo.brand }}</text>
  8. <text class="navbar-divider">|</text>
  9. <text class="navbar-item" @click="handleModelClick">{{ topInfo.model }}</text>
  10. <text class="navbar-divider">|</text>
  11. <text class="navbar-item price" @click="handlePriceClick">¥{{ topInfo.price }}</text>
  12. </view>
  13. </template>
  14. <template slot="right">
  15. <view class="navbar-right" @click="handleAddClick">
  16. <image src="/static/icons/plus.png" mode="scaleToFill" class="add-icon" />
  17. <text class="add-text">加一单</text>
  18. </view>
  19. </template>
  20. </u-navbar>
  21. <!-- 收单列表切换 -->
  22. <u-tabs
  23. keyName="brand"
  24. :list="receiptList"
  25. @click="handleReceiptClick"
  26. class="receipt-tabs"
  27. />
  28. <!-- 订单详情视图 -->
  29. <OrderDetailView
  30. :order-detail="orderDetail"
  31. :top-info="topInfo"
  32. :order-id="orderId"
  33. :current-receipt="currentReceipt"
  34. />
  35. <!-- 加一单模态窗 -->
  36. <u-modal
  37. :show="addOneModalVisible"
  38. title="加一单"
  39. showCancelButton
  40. @cancel="handleAddOneCancel"
  41. @confirm="handleAddOneConfirm"
  42. >
  43. <view class="add-one-modal-content">
  44. <u-button
  45. type="primary"
  46. plain
  47. @click="showBrandSelector = true"
  48. class="brand-select-btn"
  49. >
  50. {{ currentAddBrand.dictLabel || '点击请选择品牌' }}
  51. </u-button>
  52. </view>
  53. </u-modal>
  54. <!-- 品牌选择器 -->
  55. <u-picker
  56. :show="showBrandSelector"
  57. :columns="brandColumns"
  58. keyName="dictLabel"
  59. @confirm="handleBrandConfirm"
  60. @cancel="showBrandSelector = false"
  61. />
  62. <!-- 编辑品牌选择器 -->
  63. <u-picker
  64. :show="editBrandSelectorVisible"
  65. :columns="brandColumns"
  66. keyName="dictLabel"
  67. @confirm="handleEditBrandConfirm"
  68. @cancel="editBrandSelectorVisible = false"
  69. />
  70. <!-- 修改型号/价格弹窗 -->
  71. <CustomModal
  72. :visible="modalVisible"
  73. :title="modalConfig.title"
  74. :value="modalConfig.value"
  75. :placeholder="modalConfig.placeholder"
  76. @cancel="handleModalCancel"
  77. @confirm="handleModalConfirm"
  78. />
  79. </view>
  80. </template>
  81. <script>
  82. import OrderDetailView from './components/OrderDetailView.vue'
  83. import CustomModal from './components/CustomModal.vue'
  84. export default {
  85. name: 'OrderDetailIndex',
  86. components: {
  87. OrderDetailView,
  88. CustomModal
  89. },
  90. data() {
  91. return {
  92. // 顶部信息
  93. topInfo: {
  94. brand: '',
  95. model: '',
  96. price: ''
  97. },
  98. // 路由参数
  99. orderId: '',
  100. clueId: '',
  101. item: '',
  102. type: '',
  103. // 订单详情
  104. orderDetail: {},
  105. // 收单列表
  106. receiptList: [],
  107. // 当前选中的收单
  108. currentReceipt: {},
  109. // 模态窗状态
  110. addOneModalVisible: false,
  111. showBrandSelector: false,
  112. editBrandSelectorVisible: false,
  113. modalVisible: false,
  114. // 品牌选择相关
  115. brandColumns: [[]],
  116. currentAddBrand: {},
  117. // 模态窗配置
  118. modalConfig: {
  119. title: '',
  120. value: '',
  121. placeholder: ''
  122. },
  123. currentEditField: ''
  124. }
  125. },
  126. onLoad(options) {
  127. this.initParams(options)
  128. this.loadOrderDetail()
  129. this.loadReceiptList()
  130. },
  131. methods: {
  132. /**
  133. * 初始化参数
  134. */
  135. initParams(options) {
  136. const { item, orderId, type, clueId } = options
  137. this.item = item || ''
  138. this.orderId = orderId || ''
  139. this.type = type || ''
  140. this.clueId = clueId || ''
  141. },
  142. /**
  143. * 加载订单详情
  144. */
  145. async loadOrderDetail() {
  146. try {
  147. const res = await uni.$u.api.getClueSendFormVoByOrderId({
  148. id: this.orderId
  149. })
  150. if (res.code === 200) {
  151. this.orderDetail = res.data || {}
  152. }
  153. } catch (error) {
  154. console.error('加载订单详情失败:', error)
  155. uni.$u.toast('加载订单详情失败')
  156. }
  157. },
  158. /**
  159. * 加载收单列表
  160. */
  161. async loadReceiptList() {
  162. try {
  163. const res = await uni.$u.api.clueReceiptFormListByOrderId(this.orderId)
  164. if (res.code === 200) {
  165. this.receiptList = res.data || []
  166. // 默认选择第一个收单
  167. if (this.receiptList.length > 0) {
  168. this.handleReceiptClick(this.receiptList[0])
  169. }
  170. }
  171. } catch (error) {
  172. console.error('加载收单列表失败:', error)
  173. uni.$u.toast('加载收单列表失败')
  174. }
  175. },
  176. /**
  177. * 点击收单项
  178. */
  179. handleReceiptClick(item) {
  180. this.currentReceipt = item
  181. this.topInfo.brand = item.brand || '暂无'
  182. this.topInfo.model = item.model || '暂无'
  183. this.topInfo.price = item.sellingPrice || '暂无'
  184. },
  185. /**
  186. * 点击品牌
  187. */
  188. handleBrandClick() {
  189. this.editBrandSelectorVisible = true
  190. this.loadBrandList()
  191. },
  192. /**
  193. * 点击型号
  194. */
  195. handleModelClick() {
  196. this.modalConfig = {
  197. title: '修改型号',
  198. value: this.currentReceipt.model || '',
  199. placeholder: '请输入型号'
  200. }
  201. this.currentEditField = 'model'
  202. this.modalVisible = true
  203. },
  204. /**
  205. * 点击价格
  206. */
  207. handlePriceClick() {
  208. this.modalConfig = {
  209. title: '修改价格',
  210. value: this.currentReceipt.sellingPrice?.toString() || '',
  211. placeholder: '请输入价格'
  212. }
  213. this.currentEditField = 'price'
  214. this.modalVisible = true
  215. },
  216. /**
  217. * 点击加一单
  218. */
  219. handleAddClick() {
  220. this.addOneModalVisible = true
  221. this.loadBrandList()
  222. },
  223. /**
  224. * 加载品牌列表
  225. */
  226. async loadBrandList() {
  227. try {
  228. const res = await this.$getDicts('crm_form_brand')
  229. this.brandColumns = [res]
  230. } catch (error) {
  231. console.error('加载品牌列表失败:', error)
  232. }
  233. },
  234. /**
  235. * 确认修改模态窗
  236. */
  237. async handleModalConfirm(value) {
  238. try {
  239. if (this.currentEditField === 'model') {
  240. await uni.$u.api.updateReceiptForm({
  241. model: value,
  242. id: this.currentReceipt.id
  243. })
  244. } else if (this.currentEditField === 'price') {
  245. await uni.$u.api.updateReceiptForm({
  246. sellingPrice: value,
  247. id: this.currentReceipt.id
  248. })
  249. }
  250. uni.$u.toast('修改成功')
  251. this.loadReceiptList()
  252. } catch (error) {
  253. console.error('修改失败:', error)
  254. uni.$u.toast('修改失败')
  255. } finally {
  256. this.modalVisible = false
  257. }
  258. },
  259. /**
  260. * 取消修改模态窗
  261. */
  262. handleModalCancel() {
  263. this.modalVisible = false
  264. },
  265. /**
  266. * 确认编辑品牌
  267. */
  268. async handleEditBrandConfirm(data) {
  269. try {
  270. await uni.$u.api.updateReceiptForm({
  271. brand: data.value[0].dictValue,
  272. id: this.currentReceipt.id
  273. })
  274. uni.$u.toast('修改成功')
  275. this.loadReceiptList()
  276. } catch (error) {
  277. console.error('修改品牌失败:', error)
  278. uni.$u.toast('修改失败')
  279. } finally {
  280. this.editBrandSelectorVisible = false
  281. }
  282. },
  283. /**
  284. * 确认选择品牌(加一单)
  285. */
  286. handleBrandConfirm(data) {
  287. this.currentAddBrand = data.value[0]
  288. this.showBrandSelector = false
  289. },
  290. /**
  291. * 确认加一单
  292. */
  293. async handleAddOneConfirm() {
  294. try {
  295. await uni.$u.api.addReceiptForm({
  296. brand: this.currentAddBrand.dictValue,
  297. sendFormId: this.orderId,
  298. clueId: this.clueId
  299. })
  300. uni.$u.toast('添加成功')
  301. this.loadReceiptList()
  302. } catch (error) {
  303. console.error('添加失败:', error)
  304. uni.$u.toast('添加失败')
  305. } finally {
  306. this.addOneModalVisible = false
  307. this.currentAddBrand = {}
  308. }
  309. },
  310. /**
  311. * 取消加一单
  312. */
  313. handleAddOneCancel() {
  314. this.addOneModalVisible = false
  315. this.currentAddBrand = {}
  316. }
  317. }
  318. }
  319. </script>
  320. <style scoped lang="scss">
  321. .order-detail-container {
  322. min-height: 100vh;
  323. background-color: #f9fafb;
  324. }
  325. .navbar-center {
  326. display: flex;
  327. align-items: center;
  328. background-color: #fff;
  329. border-radius: 40rpx;
  330. padding: 10rpx 20rpx;
  331. box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
  332. }
  333. .navbar-item {
  334. font-weight: bold;
  335. color: #333;
  336. font-size: 28rpx;
  337. &.price {
  338. color: blueviolet;
  339. }
  340. }
  341. .navbar-divider {
  342. margin: 0 15rpx;
  343. color: #ddd;
  344. font-size: 28rpx;
  345. }
  346. .navbar-right {
  347. display: flex;
  348. flex-direction: column;
  349. align-items: center;
  350. justify-content: center;
  351. font-size: 20rpx;
  352. color: blueviolet;
  353. }
  354. .add-icon {
  355. width: 30rpx;
  356. height: 30rpx;
  357. }
  358. .add-text {
  359. margin-top: 4rpx;
  360. }
  361. .receipt-tabs {
  362. background-color: #fff;
  363. }
  364. .add-one-modal-content {
  365. padding: 20rpx 0;
  366. }
  367. .brand-select-btn {
  368. width: 100%;
  369. }
  370. </style>