detail.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. <template>
  2. <view class="detail" @click="handleClickOutside">
  3. <u-navbar class="nav_bar" title="商品详情档案" :autoBack="true" :placeholder="true" rightIcon="more-dot-fill"
  4. v-hideNav></u-navbar>
  5. <u-swiper :list="imgsUrl" keyName="url" indicator indicatorMode="line" circular>
  6. <!-- <template v-slot:item="{ item, index }">
  7. <view style="width: 100%; height: 600rpx;">
  8. <image :src="item.url" mode="aspectFill" style="width: 100%; height: 100%; object-fit: cover;"></image>
  9. </view>
  10. </template> -->
  11. </u-swiper>
  12. <!-- 立即下架按钮 -->
  13. <view class="immediate_off_shelf">
  14. <u-button type="error" shape="circle" size="large" @click="handleOffShelf" :disabled="lockStatus === '1' || globalEditMode">
  15. <u-icon :name="downStatus == '0' ? 'arrow-upward' : 'arrow-downward'" size="38rpx"
  16. color="#ffffff"></u-icon>
  17. <text>{{ downStatus == '0' ? '立即上架' : '立即下架' }}</text>
  18. </u-button>
  19. </view>
  20. <!-- 轮播图下方操作按钮 -->
  21. <view class="swiper_actions">
  22. <view class="action_item" @click="handleDownload">
  23. <u-icon name="download" size="44rpx" color="#606266"></u-icon>
  24. <text class="action_text">下载图文</text>
  25. </view>
  26. <view class="action_item" @click="handleShare">
  27. <u-icon name="share" size="44rpx" color="#606266"></u-icon>
  28. <text class="action_text">分享</text>
  29. </view>
  30. <view class="action_item" @click="handleEditImgs">
  31. <u-icon name="camera" size="44rpx" color="#606266"></u-icon>
  32. <text class="action_text">编辑图片</text>
  33. <u-modal :show="showEditImgsModal" title="编辑图片" showCancelButton @confirm="confirmEditImgs" @cancel="cancelEditImgs">
  34. <imgs-row-scroll v-if="tempImgsUrl.length > 0" :isShowDeleteIcon="true" keyName="url"
  35. @deleteImgInfo="getDeleteImgInfo" imgMode="aspectFill" :totalWidth="400" :images="tempImgsUrl"
  36. :previewEnabled="true" :imageWidth="150" :imageHeight="150"></imgs-row-scroll>
  37. <u-upload @afterRead="afterRead" multiple></u-upload>
  38. </u-modal>
  39. </view>
  40. <view class="action_item" @click="handleCutImg">
  41. <u-icon name="cut" size="44rpx" color="#606266"></u-icon>
  42. <text class="action_text">智能抠图</text>
  43. </view>
  44. </view>
  45. <!-- 核心信息区域 -->
  46. <view class="core_info">
  47. <view class="section_title">核心信息</view>
  48. <view class="info_row" v-if="getWarehouseFieldPermissions('dictLabel','read')">
  49. <view class="info_label">品牌</view>
  50. <view class="info_value" @click.stop="showBrandlList()">
  51. <!-- <u-input v-if="editMode.dictLabel" v-model="tempValues.dictLabel" :autoFocus="true" @blur="!globalEditMode && saveEditField('dictLabel', tempValues.dictLabel, 'dictLabel')" /> -->
  52. <span>{{ coreInfo.dictLabel || '-' }}</span>
  53. <BrandList ref="brandListRef" @selectedBrand="handleSelectedBrand"></BrandList>
  54. </view>
  55. </view>
  56. <view class="info_row" v-if="getWarehouseFieldPermissions('model','read')">
  57. <view class="info_label">型号</view>
  58. <view class="info_value" @click.stop="toggleEditField('model', coreInfo.model)">
  59. <u-input v-if="editMode.model" v-model="tempValues.model" :autoFocus="true"
  60. @blur="!globalEditMode && saveEditField('model', tempValues.model, 'model')" />
  61. <span v-else>{{ coreInfo.model || '-' }}</span>
  62. </view>
  63. </view>
  64. <view class="info_row" v-if="getWarehouseFieldPermissions('indentifyCode','read')">
  65. <view class="info_label">独立编码</view>
  66. <view class="info_value code" @click.stop="toggleEditField('indentifyCode', coreInfo.indentifyCode)">
  67. <u-input v-if="editMode.indentifyCode" v-model="tempValues.indentifyCode" :autoFocus="true"
  68. @blur="!globalEditMode && saveEditField('indentifyCode', tempValues.indentifyCode, 'indentifyCode')" />
  69. <span v-else>{{ coreInfo.indentifyCode || '-' }}</span>
  70. </view>
  71. </view>
  72. <view class="info_row" v-if="getWarehouseFieldPermissions('stockStatus','read')">
  73. <view class="info_label">是否入库</view>
  74. <view class="info_value">{{ stockStatusFormatter(coreInfo.stockStatus) }}</view>
  75. </view>
  76. <view class="info_row" v-if="getWarehouseFieldPermissions('createTime','read')">
  77. <view class="info_label">入库日期</view>
  78. <view class="info_value">{{ coreInfo.createTime || '-' }}</view>
  79. </view>
  80. <view class="info_row" v-if="getWarehouseFieldPermissions('payType','read')">
  81. <view class="info_label">付款方式</view>
  82. <view class="info_value">{{ payTypeFormatter(coreInfo.payType) }}</view>
  83. </view>
  84. <view class="info_row" v-if="getWarehouseFieldPermissions('recycleSituation','read')">
  85. <view class="info_label">回收情况</view>
  86. <view class="info_value">{{ recycleSituationFormatter(coreInfo.recycleSituation) }}</view>
  87. </view>
  88. <view class="info_row col" v-if="getWarehouseFieldPermissions('desc','read')">
  89. <view class="info_label">备注信息</view>
  90. <view class="info_value note" @click.stop="toggleEditField('desc', coreInfo.desc)">
  91. <textarea v-if="editMode.desc" v-model="tempValues.desc" :autoFocus="true" rows="3"
  92. @blur="!globalEditMode && saveEditField('desc', tempValues.desc, 'desc')" />
  93. <span v-else>{{ coreInfo.desc || '-' }}</span>
  94. </view>
  95. </view>
  96. </view>
  97. <!-- 财务与价格区域 -->
  98. <view class="finance_price">
  99. <view class="section_title">财务与价格</view>
  100. <view class="price_group">
  101. <view class="price_item" v-if="getWarehouseFieldPermissions('costPrice','read')">
  102. <view class="price_label">总成本价</view>
  103. <view class="price_value original"
  104. @click.stop="toggleEditField('costPrice', coreInfo.costPrice)">
  105. <u-input v-if="editMode.costPrice" v-model="tempValues.costPrice" :autoFocus="true"
  106. @blur="!globalEditMode && saveEditField('costPrice', tempValues.costPrice, 'costPrice')" />
  107. <span v-else>¥{{ coreInfo.costPrice || '-' }}</span>
  108. </view>
  109. </view>
  110. <view class="price_item" v-if="getWarehouseFieldPermissions('peerPrice','read')">
  111. <view class="price_label">同行价格</view>
  112. <view class="price_value additional"
  113. @click.stop="toggleEditField('peerPrice', coreInfo.peerPrice)">
  114. <u-input v-if="editMode.peerPrice" v-model="tempValues.peerPrice" :autoFocus="true"
  115. @blur="!globalEditMode && saveEditField('peerPrice', tempValues.peerPrice, 'peerPrice')" />
  116. <span v-else>¥{{ coreInfo.peerPrice || '-' }}</span>
  117. </view>
  118. </view>
  119. </view>
  120. <view class="price_group">
  121. <view class="price_item" v-if="getWarehouseFieldPermissions('agentPrice','read')">
  122. <view class="price_label">代理价格</view>
  123. <view class="price_value agent" @click.stop="toggleEditField('agentPrice', coreInfo.agentPrice)">
  124. <u-input v-if="editMode.agentPrice" v-model="tempValues.agentPrice" :autoFocus="true"
  125. @blur="!globalEditMode && saveEditField('agentPrice', tempValues.agentPrice, 'agentPrice')" />
  126. <span v-else>¥{{ coreInfo.agentPrice || '-' }}</span>
  127. </view>
  128. </view>
  129. <view class="price_item" v-if="getWarehouseFieldPermissions('price','read')">
  130. <view class="price_label">官方指导价</view>
  131. <view class="price_value original" @click.stop="toggleEditField('price', coreInfo.price)">
  132. <u-input v-if="editMode.price" v-model="tempValues.price" :autoFocus="true"
  133. @blur="!globalEditMode && saveEditField('price', tempValues.price, 'price')" />
  134. <span v-else>¥{{ coreInfo.price || '-' }}</span>
  135. </view>
  136. </view>
  137. </view>
  138. <view class="price_group">
  139. <view class="price_item" v-if="getWarehouseFieldPermissions('salePrice','read')">
  140. <view class="price_label">销售价格</view>
  141. <view class="price_value suggested"
  142. @click.stop="toggleEditField('salePrice', coreInfo.salePrice)">
  143. <u-input v-if="editMode.salePrice" v-model="tempValues.salePrice" :autoFocus="true"
  144. @blur="!globalEditMode && saveEditField('salePrice', tempValues.salePrice, 'salePrice')" />
  145. <span v-else>¥{{ coreInfo.salePrice || '-' }}</span>
  146. </view>
  147. </view>
  148. <view class="price_item" v-if="getWarehouseFieldPermissions('actualPrice','read')">
  149. <view class="price_label">实价</view>
  150. <view class="price_value suggested"
  151. @click.stop="toggleEditField('actualPrice', coreInfo.actualPrice)">
  152. <u-input v-if="editMode.actualPrice" v-model="tempValues.actualPrice" :autoFocus="true"
  153. @blur="!globalEditMode && saveEditField('actualPrice', tempValues.actualPrice, 'actualPrice')" />
  154. <span v-else>¥{{ coreInfo.actualPrice || '-' }}</span>
  155. </view>
  156. </view>
  157. </view>
  158. </view>
  159. <!-- 溯源与位置区域 -->
  160. <view class="traceability_productPosition">
  161. <view class="section_title">溯源与位置</view>
  162. <view class="info_row" v-if="getWarehouseFieldPermissions('productPosition','read')">
  163. <view class="info_label">商品位置</view>
  164. <view class="info_value" @click.stop="toggleEditField('productPosition', coreInfo.productPosition)">
  165. <u-input v-if="editMode.productPosition" v-model="tempValues.productPosition" :autoFocus="true"
  166. @blur="!globalEditMode && saveEditField('productPosition', tempValues.productPosition, 'productPosition')" />
  167. <span v-else>{{ coreInfo.productPosition || '-' }}</span>
  168. </view>
  169. </view>
  170. <view class="info_row" v-if="getWarehouseFieldPermissions('recyclePerson','read')">
  171. <view class="info_label">回收人员</view>
  172. <view class="info_value" @click.stop="showRecyclePersonPicker">
  173. <span>{{ coreInfo.recyclePerson || '-' }}</span>
  174. <personPicker ref="recyclePersonPickerRef" title="请选择回收人员"
  175. @selectPerson="handleSelectRecyclePerson">
  176. </personPicker>
  177. </view>
  178. </view>
  179. <view class="info_row" v-if="getWarehouseFieldPermissions('identifyingPerson','read')">
  180. <view class="info_label">鉴定人员</view>
  181. <view class="info_value" @click.stop="showIdentifyingPersonPicker">
  182. <span>{{ coreInfo.identifyingPerson || '-' }}</span>
  183. <personPicker ref="identifyingPersonPickerRef" title="请选择鉴定人员"
  184. @selectPerson="handleSelectIdentifyingPerson"></personPicker>
  185. </view>
  186. </view>
  187. <view class="action_button">
  188. <u-button type="primary" plain size="mini" @click="viewLog">查看操作日志({{ coreInfo.logTotal ||
  189. '-'}}条)</u-button>
  190. <u-modal :show="logShow" title="日志" :closeOnClickOverlay="true" :showConfirmButton="false"
  191. @close="logShow = false">
  192. <view class="log_list">
  193. <view v-for="value in logList" :key="value.id" class="log_item">
  194. {{ value.createTime }}{{ value.name }}{{ value.operation }}
  195. </view>
  196. </view>
  197. </u-modal>
  198. </view>
  199. </view>
  200. <!-- 底部功能按钮栏 -->
  201. <view :class="['bottom_bar', { 'fourPart': coreInfo.stockStatus === '1', 'fivePart': coreInfo.stockStatus === '0' }]">
  202. <view class="bar_item" @click.stop="globalEditMode ? confirmGlobalEdit() : enterGlobalEdit()">
  203. <u-icon :name="globalEditMode ? 'checkbox-mark' : 'edit-pen'" size="46rpx"
  204. :color="globalEditMode ? '#10b981' : '#9ca3af'"></u-icon>
  205. <text class="bar_text">{{ globalEditMode ? '确定' : '编辑' }}</text>
  206. </view>
  207. <view :class="['bar_item', { 'disabled': globalEditMode}]" @click.stop="lockGoods">
  208. <u-icon :name="lockStatus === '1' ? 'lock-open' : 'lock'" size="46rpx" color="#9ca3af"></u-icon>
  209. <text class="bar_text">{{ lockStatus === '1' ? '解锁' : '锁单' }}</text>
  210. </view>
  211. <view :class="['bar_item', { 'disabled': globalEditMode}]">
  212. <image class="bar_icon" src="../../../static/icons/print.png" alt=""></image>
  213. <text class="bar_text">打印</text>
  214. </view>
  215. <view class="bar_item" v-if="coreInfo.stockStatus === '0'" @click.stop="handleConfirmStockIn">
  216. <view class="primary blue">
  217. <image class="bar_img" src="../../../static/icons/stockIn.png" alt=""></image>
  218. <text class="bar_text">确认入库</text>
  219. </view>
  220. </view>
  221. <view :class="['bar_item', { 'disabled': lockStatus === '1' || globalEditMode || downStatus == '0'}]" @click="handleOpenOrder">
  222. <view class="primary orange">
  223. <u-icon name="bag" size="44rpx" color="#fff"></u-icon>
  224. <text class="bar_text">开单</text>
  225. </view>
  226. </view>
  227. </view>
  228. </view>
  229. </template>
  230. <script>
  231. import BrandList from '@/components/brand-list/index.vue'
  232. import personPicker from '@/components/person-picker/index.vue'
  233. import imgsRowScroll from '@/components/imgs-row-scroll/index.vue'
  234. import { getWarehouseButtonPermissions,getWarehouseFieldPermissions } from '@/utils/util.js'
  235. import { recycleSituationList } from '../js/public.js'
  236. export default {
  237. components: {
  238. BrandList,
  239. personPicker,
  240. imgsRowScroll,
  241. },
  242. data() {
  243. return {
  244. // 核心信息模拟数据
  245. coreInfo: {},
  246. // 编辑状态管理
  247. editMode: {
  248. model: false,
  249. indentifyCode: false,
  250. desc: false,
  251. costPrice: false,
  252. peerPrice: false,
  253. agentPrice: false,
  254. salePrice: false,
  255. actualPrice: false,
  256. price: false,
  257. productPosition: false,
  258. },
  259. // 全局编辑模式
  260. globalEditMode: false,
  261. // 临时存储编辑值
  262. tempValues: {},
  263. goodsId: '',
  264. logShow: false,
  265. logList: [],
  266. imgsUrl: [],
  267. lockStatus: '',//锁单状态 0:未锁单 1:已锁单
  268. downStatus: '',//下架状态 0:已下架 1:已上架
  269. showEditImgsModal: false,
  270. tempImgsUrl: [],
  271. }
  272. },
  273. onLoad(options) {
  274. this.goodsId = options.id;
  275. this.getGoodsDetail();
  276. },
  277. methods: {
  278. getWarehouseButtonPermissions:getWarehouseButtonPermissions,
  279. getWarehouseFieldPermissions:getWarehouseFieldPermissions,
  280. // 分享
  281. handleShare() {
  282. uni.showToast({
  283. title: '分享功能暂未开放',
  284. icon: 'none'
  285. })
  286. },
  287. // 智能抠图
  288. handleCutImg() {
  289. uni.showToast({
  290. title: '智能抠图功能暂未开放',
  291. icon: 'none'
  292. })
  293. },
  294. // 是否入库格式化
  295. stockStatusFormatter(val){
  296. switch (val) {
  297. case '1':
  298. return '已入库'
  299. case '0':
  300. return '未入库'
  301. default:
  302. return '-'
  303. }
  304. },
  305. payTypeFormatter(val){
  306. switch (val) {
  307. case '1':
  308. return '微信'
  309. case '2':
  310. return '支付宝'
  311. case '3':
  312. return '银行卡'
  313. case '4':
  314. return '现金'
  315. case '5':
  316. return '数字货币'
  317. case '6':
  318. return '挂账'
  319. default:
  320. return '-'
  321. }
  322. },
  323. // 回收情况格式化
  324. recycleSituationFormatter(val){
  325. let item = recycleSituationList.find(item => item.value == val)
  326. return item ? item.name : '-'
  327. },
  328. // 锁单
  329. lockGoods() {
  330. if(!this.getWarehouseButtonPermissions('lockOrder')) return false
  331. if (this.globalEditMode) {
  332. uni.showToast({
  333. title: '编辑状态下不能操作',
  334. icon: 'none'
  335. })
  336. return
  337. }
  338. uni.$u.api.wareHouseLock({
  339. id: this.goodsId,
  340. lockStatus: this.lockStatus === '1' ? '0' : '1',
  341. }).then(res => {
  342. uni.showToast({
  343. type: "success",
  344. title: this.lockStatus === '1' ? '解锁成功' : '锁单成功',
  345. icon: 'success'
  346. })
  347. this.getGoodsDetail();
  348. }).catch((error) => {
  349. uni.showToast({
  350. title: error || '操作失败',
  351. icon: 'none'
  352. })
  353. })
  354. },
  355. showRecyclePersonPicker() {
  356. this.$refs.recyclePersonPickerRef.open();
  357. },
  358. // 处理选中回收人员
  359. handleSelectRecyclePerson(person) {
  360. this.coreInfo.recyclePerson = person.label;
  361. this.coreInfo.recyclePersonId = person.id;
  362. this.submitEdit(this.coreInfo)
  363. },
  364. // 显示鉴定人员选择器
  365. showIdentifyingPersonPicker() {
  366. this.$refs.identifyingPersonPickerRef.open();
  367. },
  368. // 处理选中鉴定人员
  369. handleSelectIdentifyingPerson(person) {
  370. this.coreInfo.identifyingPerson = person.label;
  371. this.coreInfo.identifyingPersonId = person.id;
  372. this.submitEdit(this.coreInfo)
  373. },
  374. // 显示品牌列表
  375. showBrandlList() {
  376. if(!this.getWarehouseFieldPermissions('dictValue','edit')) return false
  377. this.$refs.brandListRef.showBrandList();
  378. },
  379. // 处理选中品牌
  380. handleSelectedBrand(info) {
  381. this.coreInfo.dictLabel = info.dictLabel;
  382. this.coreInfo.dictValue = info.dictValue;
  383. this.submitEdit(this.coreInfo)
  384. },
  385. // 获取商品详情
  386. getGoodsDetail() {
  387. uni.$u.api.wareHouseDetail({
  388. id: this.goodsId,
  389. userId: this.$store.state.user.userInfo.userId,
  390. }).then(res => {
  391. this.coreInfo = res.data;
  392. this.imgsUrl = res.data.goodPicFileList || [];
  393. this.lockStatus = res.data.lockStatus;
  394. this.downStatus = res.data.downStatus;
  395. });
  396. },
  397. // 打开销售业务开单页面
  398. handleOpenOrder() {
  399. if(!getWarehouseButtonPermissions('openOrder')) return false
  400. if (this.lockStatus === '1') {
  401. uni.showToast({
  402. title: '已锁单,不能开单',
  403. icon: 'none'
  404. })
  405. return
  406. }
  407. if (this.globalEditMode) {
  408. uni.showToast({
  409. title: '编辑状态下不能开单',
  410. icon: 'none'
  411. })
  412. return
  413. }
  414. if(this.downStatus === '0'){
  415. uni.showToast({
  416. title: '已下架,不能开单',
  417. icon: 'none'
  418. })
  419. return
  420. }
  421. const params = {
  422. id: this.goodsId,
  423. url: this.imgsUrl[0]?.url,
  424. dictLabel: this.coreInfo.dictLabel,
  425. dictValue: this.coreInfo.dictValue,
  426. model: this.coreInfo.model,
  427. agentPrice: this.coreInfo.agentPrice,
  428. price: this.coreInfo.price,
  429. recyclePerson: this.coreInfo.recyclePerson,
  430. recyclePersonId: this.coreInfo.recyclePersonId,
  431. type: this.coreInfo.type,
  432. }
  433. uni.navigateTo({
  434. url: '/pages/wareHouse/components/openOrder?params=' + JSON.stringify(params),
  435. });
  436. },
  437. handleConfirmStockIn(){
  438. this.coreInfo.stockStatus = '1';
  439. this.submitEdit(this.coreInfo)
  440. },
  441. viewLog() {
  442. if(!getWarehouseButtonPermissions('viewLog')) return false
  443. uni.$u.api.wareHouseLog({
  444. id: this.goodsId,
  445. userId: this.$store.state.user.userInfo.userId,
  446. }).then(res => {
  447. this.logList = res.data;
  448. this.logShow = true;
  449. });
  450. },
  451. // 立即下架按钮
  452. handleOffShelf() {
  453. if(!getWarehouseButtonPermissions('shelf')) return false
  454. if (this.lockStatus === '1') {
  455. uni.showToast({
  456. title: '已锁单,不能下架',
  457. icon: 'none'
  458. })
  459. return
  460. }
  461. if (this.globalEditMode) {
  462. uni.showToast({
  463. title: '编辑状态下不能操作',
  464. icon: 'none'
  465. })
  466. return
  467. }
  468. uni.$u.api.wareHouseDown({
  469. id: this.goodsId,
  470. downStatus: this.downStatus === '1' ? '0' : '1',
  471. }).then(() => {
  472. uni.showToast({
  473. title: this.downStatus === '1' ? '下架成功' : '上架成功',
  474. icon: 'success'
  475. })
  476. this.getGoodsDetail();
  477. }).catch(() => {
  478. uni.showToast({
  479. title: '操作失败',
  480. icon: 'none'
  481. })
  482. })
  483. },
  484. // 切换单个字段的编辑状态
  485. toggleEditField(field, value) {
  486. if(!getWarehouseButtonPermissions('edit')) return false
  487. // 如果不是全局编辑模式
  488. if (!this.globalEditMode) {
  489. // 重置所有编辑状态
  490. this.resetEditMode();
  491. // 设置当前字段为编辑状态
  492. this.editMode[field] = true;
  493. // 保存临时值
  494. this.tempValues[field] = value;
  495. }
  496. },
  497. // 保存单个字段的编辑值
  498. saveEditField(field, newValue, fieldName) {
  499. this.coreInfo[fieldName] = newValue;
  500. this.editMode[field] = false;
  501. delete this.tempValues[field];
  502. console.log(`保存${field}字段值: ${newValue}`);
  503. this.submitEdit(this.coreInfo);
  504. },
  505. // 进入全局编辑模式
  506. enterGlobalEdit() {
  507. if(!getWarehouseButtonPermissions('edit')) return false
  508. this.globalEditMode = true;
  509. // 设置所有可编辑字段为编辑状态
  510. this.editMode = {
  511. model: true,
  512. indentifyCode: true,
  513. desc: true,
  514. costPrice: true,
  515. peerPrice: true,
  516. agentPrice: true,
  517. salePrice: true,
  518. price: true,
  519. productPosition: true,
  520. };
  521. // 保存所有字段的临时值
  522. this.tempValues = { ...this.coreInfo }
  523. },
  524. // 重置所有编辑状态
  525. resetEditMode() {
  526. Object.keys(this.editMode).forEach(key => {
  527. this.editMode[key] = false;
  528. });
  529. },
  530. submitEdit(info) {
  531. const data = {
  532. id: this.goodsId,
  533. goodPicFileList: this.imgsUrl,
  534. dictLabel: info.dictLabel,
  535. dictValue: info.dictValue,
  536. model: info.model,
  537. indentifyCode: info.indentifyCode,
  538. createTime: info.createTime,
  539. payType: info.payType,
  540. desc: info.desc,
  541. costPrice: info.costPrice,
  542. peerPrice: info.peerPrice,
  543. agentPrice: info.agentPrice,
  544. salePrice: info.salePrice,
  545. price: info.price,
  546. productPosition: info.productPosition,
  547. recyclePerson: info.recyclePerson,
  548. recyclePersonId: info.recyclePersonId,
  549. identifyingPerson: info.identifyingPerson,
  550. identifyingPersonId: info.identifyingPersonId,
  551. stockStatus: info.stockStatus,
  552. }
  553. uni.$u.api.wareHouseUpdate(data).then(res => {
  554. uni.showToast({
  555. title: '编辑成功',
  556. icon: 'success'
  557. });
  558. this.getGoodsDetail();
  559. this.$emit('editSuccess')
  560. }).catch(() => {
  561. uni.showToast({
  562. title: '操作失败',
  563. icon: 'none'
  564. })
  565. })
  566. },
  567. // 点击页面其他地方保存所有编辑
  568. handleClickOutside() {
  569. if (!this.globalEditMode) {
  570. // 保存当前正在编辑的字段
  571. Object.keys(this.editMode).forEach(key => {
  572. if (this.editMode[key]) {
  573. this.saveEditField(key, this.tempValues[key], key);
  574. }
  575. });
  576. }
  577. // 当globalEditMode为true时,不执行任何操作
  578. },
  579. // 确认全局编辑
  580. confirmGlobalEdit() {
  581. this.submitEdit(this.tempValues)
  582. // 重置全局编辑模式
  583. this.globalEditMode = false;
  584. // 退出所有编辑状态
  585. this.resetEditMode();
  586. // 清空临时值,恢复初始状态
  587. this.tempValues = {};
  588. },
  589. handleDownload() {
  590. if (this.imgsUrl.length == 0) {
  591. uni.showToast({
  592. title: '暂无图片',
  593. icon: 'none'
  594. })
  595. return;
  596. }
  597. uni.showModal({
  598. title: '保存图片',
  599. content: `是否将 ${this.imgsUrl.length} 张图片保存到本地相册?`,
  600. confirmText: '保存',
  601. success: (res) => {
  602. if (res.confirm) {
  603. this.saveImagesToLocal(this.imgsUrl);
  604. }
  605. }
  606. })
  607. },
  608. saveImagesToLocal(allUrls) {
  609. uni.showToast({
  610. title: '图片保存中...',
  611. icon: 'loading'
  612. })
  613. allUrls.forEach((item, index) => {
  614. uni.downloadFile({
  615. url: item.url,
  616. success: (res) => {
  617. if (res.statusCode === 200) {
  618. uni.saveImageToPhotosAlbum({
  619. filePath: res.tempFilePath,
  620. success() {
  621. uni.showToast({
  622. title: '保存成功'
  623. })
  624. },
  625. fail: (err) => {
  626. console.error('保存到相册失败:', err);
  627. // 如果是权限问题,尝试请求权限
  628. if (err.errMsg.includes('auth denied')) {
  629. uni.showModal({
  630. title: '权限不足',
  631. content: '需要访问相册权限来保存图片,是否去设置?',
  632. success: (modalRes) => {
  633. if (modalRes.confirm) {
  634. // 打开设置页面
  635. uni.openSetting({
  636. success: (settingRes) => {
  637. console.log('设置页面结果:', settingRes);
  638. }
  639. });
  640. }
  641. }
  642. });
  643. }
  644. reject(err);
  645. }
  646. })
  647. }
  648. }
  649. })
  650. })
  651. },
  652. handleEditImgs() {
  653. if(!this.getWarehouseFieldPermissions('goodPicFileList','edit')) return false
  654. this.showEditImgsModal = true;
  655. this.tempImgsUrl = this.imgsUrl
  656. },
  657. getDeleteImgInfo(imgInfo) {
  658. this.tempImgsUrl = imgInfo.newImages
  659. },
  660. afterRead(info) {
  661. info.file.forEach(item=>{
  662. uni.$u.api.uploadFile(item.url).then((res) => {
  663. this.tempImgsUrl.push({url:res.data.url});
  664. uni.$u.toast("文件上传成功");
  665. }).catch(() => {
  666. uni.$u.toast("上传文件失败");
  667. })
  668. })
  669. },
  670. confirmEditImgs() {
  671. this.imgsUrl = this.tempImgsUrl
  672. this.submitEdit(this.coreInfo)
  673. this.showEditImgsModal = false;
  674. },
  675. cancelEditImgs() {
  676. this.tempImgsUrl = []
  677. this.showEditImgsModal = false;
  678. }
  679. }
  680. }
  681. </script>
  682. <style lang="scss" scoped>
  683. @import "../styles/detail.scss";
  684. </style>