Selaa lähdekoodia

feat:个人中心mock接口+仓库开单静态

zhangxin 2 kuukautta sitten
vanhempi
commit
95a5db0e6a

+ 0 - 52
components/custom-tab-radio/index.vue

@@ -1,52 +0,0 @@
1
-<template>
2
-  <view class="tab-radio-container" :style="{ gridTemplateColumns: `repeat(${colNum}, 1fr)` }">
3
-    <view 
4
-      class="tab-item"
5
-      v-for="(item, index) in tabList"
6
-      :key="index"
7
-      :class="{ 'tab-item--active': activeValue === item.value }"
8
-      @click="handleTabClick(item)"
9
-    >
10
-      <text class="tab-item__text">{{ item.name }}</text>
11
-    </view>
12
-  </view>
13
-</template>
14
-
15
-<script>
16
-export default {
17
-  name: "TabRadio",
18
-  props: {
19
-    tabList: {
20
-      type: Array,
21
-      required: true,
22
-      default: () => []
23
-    },
24
-    defaultActive: {
25
-      type: [String, Number],
26
-      default: ""
27
-    },
28
-    colNum: {
29
-      type: Number,
30
-      default: 4
31
-    }
32
-  },
33
-  data() {
34
-    return {
35
-      activeValue: this.defaultActive
36
-    };
37
-  },
38
-  methods: {
39
-    handleTabClick(item) {
40
-      this.activeValue = item.value;
41
-      this.$emit("tabChange", {
42
-        name: item.name,
43
-        value: item.value
44
-      });
45
-    }
46
-  }
47
-};
48
-</script>
49
-
50
-<style lang="scss" scoped>
51
-@import "./index.scss";
52
-</style>

+ 1 - 1
components/custom-tab-radio/index.scss

@@ -32,7 +32,7 @@
32 32
 
33 33
 .tab-item--active {
34 34
   border:1px solid #2563eb;
35
-  background-color: transparent;
35
+  background-color: rgba(37, 99, 235, 0.1);
36 36
   .tab-item__text {
37 37
     color: #2563eb;
38 38
     font-weight: 500;

+ 94 - 0
components/custom-tab-select/index.vue

@@ -0,0 +1,94 @@
1
+<template>
2
+  <view class="tab-radio-container" :style="{ gridTemplateColumns: `repeat(${colNum}, 1fr)` }">
3
+    <view 
4
+      class="tab-item"
5
+      :class="{ 
6
+        'tab-item--active': isMultiple ? activeValues.includes(item.value) : activeValue === item.value,
7
+        'tab-item--multiple': isMultiple
8
+      }"
9
+      v-for="(item, index) in tabList"
10
+      :key="index"
11
+      @click="handleTabClick(item)"
12
+    >
13
+      <text class="tab-item__text">{{ item.name }}</text>
14
+      <!-- <view v-if="isMultiple" class="tab-item__checkbox" :class="{ 'tab-item__checkbox--checked': activeValues.includes(item.value) }">
15
+        <view v-if="activeValues.includes(item.value)" class="tab-item__checkbox-inner"></view>
16
+      </view> -->
17
+    </view>
18
+  </view>
19
+</template>
20
+
21
+<script>
22
+export default {
23
+  name: "TabRadio",
24
+  props: {
25
+    tabList: {
26
+      type: Array,
27
+      required: true,
28
+      default: () => []
29
+    },
30
+    defaultActive: {
31
+      type: [String, Number, Array],
32
+      default: ""
33
+    },
34
+    colNum: {
35
+      type: Number,
36
+      default: 4
37
+    },
38
+    mode: {
39
+      type: String,
40
+      default: "single",
41
+      validator: (value) => ["single", "multiple"].includes(value)
42
+    }
43
+  },
44
+  computed: {
45
+    isMultiple() {
46
+      return this.mode === "multiple";
47
+    }
48
+  },
49
+  data() {
50
+    return {
51
+      activeValue: this.defaultActive,
52
+      activeValues: Array.isArray(this.defaultActive) ? this.defaultActive : []
53
+    };
54
+  },
55
+  watch: {
56
+    defaultActive: {
57
+      handler(val) {
58
+        if (this.isMultiple) {
59
+          this.activeValues = Array.isArray(val) ? val : [];
60
+        } else {
61
+          this.activeValue = val;
62
+        }
63
+      },
64
+      immediate: true
65
+    }
66
+  },
67
+  methods: {
68
+    handleTabClick(item) {
69
+      if (this.isMultiple) {
70
+        this.handleMultipleSelect(item);
71
+      } else {
72
+        this.handleSingleSelect(item);
73
+      }
74
+    },
75
+    handleSingleSelect(item) {
76
+      this.activeValue = item.value;
77
+      this.$emit("tabChange", item.value);
78
+    },
79
+    handleMultipleSelect(item) {
80
+      const index = this.activeValues.indexOf(item.value);
81
+      if (index > -1) {
82
+        this.activeValues.splice(index, 1);
83
+      } else {
84
+        this.activeValues.push(item.value);
85
+      }
86
+      this.$emit("tabChange", [...this.activeValues]);
87
+    }
88
+  }
89
+};
90
+</script>
91
+
92
+<style lang="scss" scoped>
93
+@import "./index.scss";
94
+</style>

+ 6 - 0
main.js

@@ -5,6 +5,12 @@ import store from './store'
5 5
 import uView from '@/uni_modules/uview-ui'
6 6
 Vue.use(uView)
7 7
 
8
+if (process.env.NODE_ENV === 'development') {
9
+  console.log('%c[Mock] 开发模式已启用', 'color: green; font-weight: bold;');
10
+  console.log('%c[Mock] 请启动Mock服务器: node mock-server.js', 'color: blue;');
11
+  console.log('%c[Mock] 服务器地址: http://localhost:3001', 'color: blue;');
12
+}
13
+
8 14
 
9 15
 
10 16
 // 如此配置即可

+ 91 - 0
mock-server.js

@@ -0,0 +1,91 @@
1
+const http = require('http');
2
+const url = require('url');
3
+const mockConfig = require('./mock/mockData.js');
4
+
5
+const PORT = 3001;
6
+const BASE_PATH = '/mock-api';
7
+
8
+function getMockData(requestUrl, method) {
9
+  const mockDataList = mockConfig.getMockDataList();
10
+  for (const key in mockDataList) {
11
+    const item = mockDataList[key];
12
+    if (item.url === requestUrl && item.method.toLowerCase() === method.toLowerCase()) {
13
+      return item;
14
+    }
15
+  }
16
+  return null;
17
+}
18
+
19
+function sendJson(res, statusCode, data) {
20
+  res.writeHead(statusCode, {
21
+    'Content-Type': 'application/json',
22
+    'Access-Control-Allow-Origin': '*',
23
+    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
24
+    'Access-Control-Allow-Headers': 'Content-Type, Authorization, belongSystemId, belongSystemName'
25
+  });
26
+  res.end(JSON.stringify(data));
27
+}
28
+
29
+const server = http.createServer((req, res) => {
30
+  if (req.method === 'OPTIONS') {
31
+    sendJson(res, 204, null);
32
+    return;
33
+  }
34
+
35
+  const parsedUrl = url.parse(req.url, true);
36
+  const pathname = parsedUrl.pathname;
37
+  const method = req.method;
38
+
39
+  if (!pathname.startsWith(BASE_PATH)) {
40
+    sendJson(res, 404, { code: 404, msg: 'Not Found', data: null });
41
+    return;
42
+  }
43
+
44
+  const apiPath = pathname.replace(BASE_PATH, '');
45
+
46
+  console.log(`[Mock Server] 收到请求: ${method} ${apiPath}`);
47
+  if (Object.keys(parsedUrl.query).length > 0) {
48
+    console.log(`[Mock Server] Query参数:`, parsedUrl.query);
49
+  }
50
+
51
+  const mockData = getMockData(apiPath, method);
52
+  if (mockData) {
53
+    let body = '';
54
+    req.on('data', chunk => {
55
+      body += chunk.toString();
56
+    });
57
+    req.on('end', () => {
58
+      if (body) {
59
+        try {
60
+          console.log(`[Mock Server] Body参数:`, JSON.parse(body));
61
+        } catch (e) {
62
+          console.log(`[Mock Server] Body参数:`, body);
63
+        }
64
+      }
65
+
66
+      setTimeout(() => {
67
+        sendJson(res, 200, mockData.response);
68
+        console.log(`[Mock Server] 返回Mock数据\n`);
69
+      }, mockData.delay || 300);
70
+    });
71
+  } else {
72
+    console.log(`[Mock Server] 未找到Mock配置: ${method} ${apiPath}\n`);
73
+    sendJson(res, 404, { code: 404, msg: 'Mock接口不存在', data: null });
74
+  }
75
+});
76
+
77
+server.listen(PORT, () => {
78
+  console.log('==========================================');
79
+  console.log('🟢 Mock服务器已启动');
80
+  console.log(`📡 监听地址: http://localhost:${PORT}`);
81
+  console.log(`🔗 接口前缀: ${BASE_PATH}`);
82
+  console.log('==========================================');
83
+
84
+  const mockList = mockConfig.getMockDataList();
85
+  console.log('\n已注册的Mock接口:');
86
+  Object.keys(mockList).forEach(key => {
87
+    const item = mockList[key];
88
+    console.log(`  ${item.method.toUpperCase().padEnd(6)} ${item.url}`);
89
+  });
90
+  console.log('==========================================\n');
91
+});

+ 29 - 0
mock/index.js

@@ -0,0 +1,29 @@
1
+const mockConfig = require('./mockData.js');
2
+
3
+const mockObj = {
4
+  getList: function() {
5
+    return mockConfig.getMockDataList();
6
+  },
7
+
8
+  getData: function(key) {
9
+    return mockConfig.getMockData(key);
10
+  },
11
+
12
+  add: function(key, config) {
13
+    return mockConfig.addMockData(key, config);
14
+  },
15
+
16
+  remove: function(key) {
17
+    return mockConfig.removeMockData(key);
18
+  },
19
+
20
+  isDev: function() {
21
+    return process.env.NODE_ENV === 'development';
22
+  },
23
+
24
+  getServerUrl: function() {
25
+    return 'http://localhost:3001';
26
+  }
27
+};
28
+
29
+module.exports = mockObj;

+ 140 - 0
mock/mockData.js

@@ -0,0 +1,140 @@
1
+const mockDataList = {
2
+  // 获取个人中心数据
3
+  'getPersonCards': {
4
+    method: 'get',
5
+    url: '/prod-api/crm/getPersonCards',
6
+    delay: 300,
7
+    response: {
8
+      code: 200,
9
+      msg: 'success',
10
+      data: {
11
+        todayConsume: 1234.56,//今日消耗
12
+        todayPerformance: 56789.01,//今日业绩
13
+        countTypeA: 25,//条数统计A类
14
+        countTypeB: 12,//条数统计B类
15
+        countTypeC: 8,//条数统计C类
16
+        visitCount: 15,//上门
17
+        visitRate: 85.5,//上门率
18
+        dealRate: 42.3,//成交率
19
+        roi: 3.25,//投产比
20
+        beatRate: 78.9,//击败率
21
+        level: '高级',//等级
22
+        score: 'A'//评分
23
+      }
24
+    }
25
+  },
26
+  // 个人中心-获取最新线索
27
+  'getPersonLatestClue': {
28
+    method: 'get',
29
+    url: '/prod-api/crm/getPersonLatestClue',
30
+    delay: 300,
31
+    response: {
32
+      code: 200,
33
+      msg: 'success',
34
+      data: [
35
+        {
36
+          id:1,
37
+          name:'张三',//客户名称
38
+          star:3,//客户等级
39
+          prodTitle:'LV 发财桶',//产品名称
40
+          desc:'客户说价格有点低'//客户描述
41
+        },
42
+        {
43
+          id:2,
44
+          name:'李四',//客户名称
45
+          star:3,//客户等级
46
+          prodTitle:'LV 发财桶',//产品名称
47
+          desc:'客户说价格有点低'//客户描述
48
+        },
49
+        {
50
+          id:3,
51
+          name:'张三',//客户名称
52
+          star:3,//客户等级
53
+          prodTitle:'LV 发财桶',//产品名称
54
+          desc:'客户说价格有点低'//客户描述
55
+        },
56
+        
57
+      ]
58
+    }
59
+  },
60
+  // 个人中心-近七天排名折线图
61
+  'getPersonRanking': {
62
+    method: 'get',
63
+    url: '/prod-api/crm/getPersonRanking',
64
+    delay: 300,
65
+    response: {
66
+      code: 200,
67
+      msg: 'success',
68
+      data: [
69
+        {
70
+          x: '2026-1-1',//x轴日期
71
+          y: 80,//y轴value
72
+        },
73
+        {
74
+          x: '2026-1-2',
75
+          y: 12,
76
+        },
77
+        {
78
+          x: '2026-1-3',
79
+          y: 33,
80
+        },
81
+        {
82
+          x: '2026-1-4',//日期
83
+          y: 94,
84
+        },
85
+        {
86
+          x: '2026-1-5',//日期
87
+          y: 45,
88
+        },
89
+      ]
90
+    }
91
+  },
92
+  // 个人中心-仓库卡片数据
93
+  'getWareHouseCard': {
94
+    method: 'get',
95
+    url: '/prod-api/crm/getWareHouseCard',
96
+    delay: 300,
97
+    response: {
98
+      code: 200,
99
+      msg: 'success',
100
+      data: {
101
+        totalCost: 12456.5,//总资产成本
102
+        uploadCostToday: 5678,//今日上传
103
+        outStockToday: 12,//今日出库
104
+        totalNum: 1235,//总条数
105
+      }
106
+    }
107
+  },
108
+  
109
+};
110
+
111
+function getMockDataList() {
112
+  return mockDataList;
113
+}
114
+
115
+function addMockData(key, config) {
116
+  mockDataList[key] = config;
117
+  console.log(`[Mock] 新增Mock接口: ${key}`);
118
+  return true;
119
+}
120
+
121
+function removeMockData(key) {
122
+  if (mockDataList[key]) {
123
+    delete mockDataList[key];
124
+    console.log(`[Mock] 删除Mock接口: ${key}`);
125
+    return true;
126
+  }
127
+  return false;
128
+}
129
+
130
+function getMockData(key) {
131
+  return mockDataList[key] || null;
132
+}
133
+
134
+module.exports = {
135
+  getMockDataList,
136
+  addMockData,
137
+  removeMockData,
138
+  getMockData,
139
+  mockDataList
140
+};

+ 1 - 0
package.json

@@ -23,6 +23,7 @@
23 23
 		"eslint": "^8.42.0",
24 24
 		"eslint-plugin-prettier": "^4.2.1",
25 25
 		"eslint-plugin-vue": "^9.14.1",
26
+		"mockjs": "^1.1.0",
26 27
 		"prettier": "^2.8.8",
27 28
 		"vue-inset-loader": "^1.2.6"
28 29
 	},

+ 9 - 0
pages.json

@@ -196,6 +196,15 @@
196 196
 			}
197 197
 		},
198 198
 		{
199
+			"path" : "pages/wareHouse/openOrder",	
200
+			"style" : 
201
+			{
202
+				"navigationBarTitleText" : "销售业务开单",
203
+				"enablePullDownRefresh": true,
204
+				"navigationStyle": "custom"
205
+			}
206
+		},
207
+		{
199 208
 			"path" : "pages/privateClue/index",
200 209
 			"style" : 
201 210
 			{

+ 43 - 47
pages/person/cards/index.vue

@@ -78,7 +78,7 @@
78 78
                             </view>
79 79
                             <view class="ranking_info_text">
80 80
                                 <text class="card_title">当前排名</text>
81
-                                <text class="ranking_text">击败了{{ cardData.beatRate }}的同事</text>
81
+                                <text class="ranking_text">击败了{{ cardData.beatRate }}%的同事</text>
82 82
                             </view>
83 83
                         </view>
84 84
                         <view class="ranking_details">
@@ -108,7 +108,7 @@
108 108
             </view>
109 109
         </view>
110 110
         <!-- 最新线索 -->
111
-        <view class="latest_clue">
111
+        <view class="latest_clue"  v-if="clueList.length > 0">
112 112
             <view class="clue_header">
113 113
                 <text class="card_title">最新线索</text>
114 114
                 <view class="more_btn" @click="toPrivateClue">
@@ -122,9 +122,9 @@
122 122
                         <u-icon name="star-fill" size="20" color="#facc15"></u-icon>
123 123
                         <text class="clue_name">{{ item.star }}</text>
124 124
                     </view>
125
-                    <text class="clue_name">{{ item.clueName }}</text>
125
+                    <text class="clue_name">{{ item.name }}</text>
126 126
                     <view class="clue_info">
127
-                        <text class="clue_title">{{ item.title }}</text>
127
+                        <text class="clue_title">{{ item.prodTitle }}</text>
128 128
                         <text class="clue_desc">{{ item.desc }}</text>
129 129
                     </view>
130 130
                 </view>
@@ -139,25 +139,25 @@ export default {
139 139
         return {
140 140
             // 卡片数据
141 141
             cardData: {
142
-                todayConsume: '0',
143
-                todayPerformance: '12,500',
144
-                countTypeA: '0',
145
-                countTypeB: '2',
146
-                countTypeC: '5',
147
-                visitCount: '1',
148
-                visitRate: '50%',
149
-                dealRate: '25%',
150
-                roi: '1.2',
151
-                beatRate: '60%',
152
-                level: '',
153
-                score: 'A'
142
+                todayConsume: '-',
143
+                todayPerformance: '-',
144
+                countTypeA: '-',
145
+                countTypeB: '-',
146
+                countTypeC: '-',
147
+                visitCount: '-',
148
+                visitRate: '-',
149
+                dealRate: '-',
150
+                roi: '-',
151
+                beatRate: '-',
152
+                level: '-',
153
+                score: '-'
154 154
             },
155 155
             chartData: {
156
-                categories: ["1", "2", "3", "4", "5", "6", "7"],
156
+                categories: [],
157 157
                 series: [
158 158
                     {
159 159
                         name: "核心数据",
160
-                        data: [80, 120, 90, 150, 130, 180, 160],
160
+                        data: [],
161 161
                         color: "#1890ff"
162 162
                     }
163 163
                 ]
@@ -227,39 +227,32 @@ export default {
227 227
                     margin: [0, 0, 15, 0]
228 228
                 }
229 229
             },
230
-            clueList: [
231
-                {
232
-                    star: '1',
233
-                    clueName: '张先生',
234
-                    title: 'LV 发财桶',
235
-                    desc: '已经电话沟通,待预约上门'
236
-                },
237
-                {
238
-                    star: '1',
239
-                    clueName: '李女士',
240
-                    title: 'LV 发财桶',
241
-                    desc: '客户说价格有点低...'
242
-                },
243
-                {
244
-                    star: '1',
245
-                    clueName: '王女士',
246
-                    title: 'Hermes Birkin',
247
-                    desc: '暂时没有时间接待'
248
-                },
249
-            ],
230
+            clueList: [],
250 231
         };
251 232
     },
252 233
 
253 234
     methods: {
254
-        // 获取卡片数据
255 235
         getCardData() {
256
-            // 预留数据获取逻辑
257
-            // 示例:
258
-            // uni.$u.api.getPersonCards().then(res => {
259
-            //   if (res.code === 0) {
260
-            //     this.cardData = res.data;
261
-            //   }
262
-            // });
236
+            uni.$u.api.getPersonCards().then(res => {
237
+              if (res.code === 200) {
238
+                this.cardData = res.data;
239
+              }
240
+            });
241
+        },
242
+        getClueList() {
243
+            uni.$u.api.getPersonLatestClue().then(res => {
244
+                if (res.code === 200) {
245
+                    this.clueList = res.data;
246
+                }
247
+            });
248
+        },
249
+        getChartData() {
250
+            uni.$u.api.getPersonRanking().then(res => {
251
+                if (res.code === 200) {
252
+                    this.chartData.categories = res.data.map(item => item.x);
253
+                    this.chartData.series[0].data = res.data.map(item => item.y);
254
+                }
255
+            });
263 256
         },
264 257
         // 跳转私有线索页面
265 258
         toPrivateClue() {
@@ -268,7 +261,10 @@ export default {
268 261
     },
269 262
     mounted() {
270 263
         this.getCardData();
271
-    }
264
+        this.getClueList();
265
+        this.getChartData();
266
+    },
267
+    
272 268
 };
273 269
 </script>
274 270
 

+ 115 - 26
pages/wareHouse/add.vue

@@ -9,19 +9,34 @@
9 9
                 </view>
10 10
             </u-navbar>
11 11
             <view class="form_list">
12
-                <u--form labelPosition="left" :model="formData" :rules="rules" ref="uForm" labelWidth="100%">
13
-                    <u-form-item label="商品图片" required prop="formData.imgs" borderBottom>
12
+                <u--form labelPosition="top" :model="formData" :rules="rules" ref="addForm" labelWidth="100%">
13
+                    <u-form-item borderBottom class="u-form-item-col">
14
+                        <u--textarea v-model="recognitionContent" placeholder='品牌:浪琴
15
+来源:【麒麟】私信-杰3-3
16
+实价:6500
17
+型号:L2.257.5.89.7
18
+编码:52356065
19
+日期:2021.11.09
20
+备注:全套
21
+付款方式:线上' confirmType="done" height="170" :maxlength="-1" @blur='handleRecognition'>
22
+                        </u--textarea>
23
+                        <u-button text="粘贴识别" @click="handleRecognition"></u-button>
24
+                    </u-form-item>
25
+                    <u-form-item label="商品图片" required prop="imgs" borderBottom>
14 26
                         <u-upload :fileList="goodPicFileList" @afterRead="afterReadGoodPic" @delete="deleteGoodPic"
15 27
                             name="3" multiple :maxCount="9" :previewFullImage="true"></u-upload>
16 28
                     </u-form-item>
17
-                    <u-form-item label="商品描述(详细的描述让用户更好的了解您的产品)" required prop="formData.desc" borderBottom>
18
-                        <u--textarea v-model="formData.desc" clearable :placeholder="descPlaceholder" count autoHeight
19
-                            maxlength="250" height="100" confirmType="done"></u--textarea>
29
+                    <u-form-item label="商品描述(详细的描述让用户更好的了解您的产品)" required prop="desc" borderBottom>
30
+                        <u--textarea v-model="formData.desc" clearable placeholder="95新 WHZ19219H
31
+                        CHANEL香奈儿链条单肩包
32
+                        21开 牛皮 尺寸25 4 15
33
+                        配件中溯卡" count autoHeight maxlength="250" height="100" confirmType="done"></u--textarea>
20 34
                     </u-form-item>
21
-                    <u-form-item label="商品分类" required prop="formData.type" borderBottom>
22
-                        <TabRadio :tabList="typeList" defaultActive="1" @tabChange="handleTabChangeType"></TabRadio>
35
+                    <u-form-item label="商品分类" required prop="type" borderBottom>
36
+                        <TabSelect :tabList="typeList" @tabChange="handleTabChangeType" :colNum="4" mode="single">
37
+                        </TabSelect>
23 38
                     </u-form-item>
24
-                    <u-form-item label="品牌" required prop="formData.brand" class="u-form-item-row" borderBottom>
39
+                    <u-form-item label="品牌" required prop="brand" class="u-form-item-row" borderBottom>
25 40
                         <FormSelectToPage :val="formData.brand" :url="brandToUrl" @handleClear="clear('brand')">
26 41
                         </FormSelectToPage>
27 42
                     </u-form-item>
@@ -52,9 +67,9 @@
52 67
                     <u-form-item label="官方指导价" class="u-form-item-row" borderBottom>
53 68
                         <u--input v-model="formData.price" placeholder="请输入" clearable border="none"></u--input>
54 69
                     </u-form-item>
55
-                    <u-form-item label="商品成色" required prop="formData.productCondition" borderBottom>
56
-                        <TabRadio :tabList="productConditionList" defaultActive="2" :colNum="2"
57
-                            @tabChange="handleTabChangeProductCondition"></TabRadio>
70
+                    <u-form-item label="商品成色" required prop="productCondition" borderBottom>
71
+                        <TabSelect :tabList="productConditionList" :colNum="2" mode="single"
72
+                            @tabChange="handleTabChangeProductCondition"></TabSelect>
58 73
                     </u-form-item>
59 74
                     <u-form-item label="细节图" borderBottom>
60 75
                         <u-upload :fileList="detailVideoFileList" @afterRead="afterReadDeatilVideo"
@@ -69,11 +84,11 @@
69 84
                     <u-form-item label="商品货号" class="u-form-item-row" borderBottom>
70 85
                         <u--input v-model="formData.productNo" placeholder="请输入" clearable border="none"></u--input>
71 86
                     </u-form-item>
72
-                    <u-form-item label="商品属性" required prop="formData.productAttribute" borderBottom>
73
-                        <TabRadio :tabList="productAttributeList" defaultActive="2"
74
-                            @tabChange="handleTabChangeProductAttribute"></TabRadio>
87
+                    <u-form-item label="商品属性" required prop="productAttribute" borderBottom>
88
+                        <TabSelect :tabList="productAttributeList" :colNum="4" mode="single"
89
+                            @tabChange="handleTabChangeProductAttribute"></TabSelect>
75 90
                     </u-form-item>
76
-                    <u-form-item label="库存数量" required prop="formData.stock" class="u-form-item-row" borderBottom>
91
+                    <u-form-item label="库存数量" required prop="stock" class="u-form-item-row" borderBottom>
77 92
                         <u--input v-model="formData.stock" placeholder="请输入" clearable border="none"></u--input>
78 93
                     </u-form-item>
79 94
                     <u-form-item label="总成本价" class="u-form-item-row" borderBottom>
@@ -92,13 +107,17 @@
92 107
                         <u--input v-model="formData.productPosition" placeholder="请输入" clearable
93 108
                             border="none"></u--input>
94 109
                     </u-form-item>
110
+                    <u-form-item label="手表年份" class="u-form-item-row" borderBottom>
111
+                        <u--input v-model="formData.watchYear" placeholder="请输入" clearable border="none"></u--input>
112
+                    </u-form-item>
95 113
                     <u-form-item label="鉴定人员" class="u-form-item-row" borderBottom>
96 114
                         <u--input v-model="formData.identifyingPerson" placeholder="请输入" clearable
97 115
                             border="none"></u--input>
98 116
                     </u-form-item>
99 117
                     <u-form-item label="回收类型" borderBottom>
100
-                        <TabRadio :tabList="recycleTypeList" defaultActive="2" @tabChange="handleTabChangeRecycleType">
101
-                        </TabRadio>
118
+                        <TabSelect :tabList="recycleTypeList" :colNum="4" mode="single"
119
+                            @tabChange="handleTabChangeRecycleType">
120
+                        </TabSelect>
102 121
                     </u-form-item>
103 122
                     <u-form-item label="回收人员" class="u-form-item-row" borderBottom>
104 123
                         <u--input v-model="formData.recyclePerson" disabled clearable border="none"></u--input>
@@ -111,7 +130,7 @@
111 130
                                 @delete="deleteRecycleBottom" name="1" multiple :maxCount="1" accept="image"></u-upload>
112 131
                         </view>
113 132
                     </u-form-item>
114
-                    <u-form-item label="回收时间" required prop="formData.recycleTime" class="u-form-item-row" borderBottom
133
+                    <u-form-item label="回收时间" required prop="recycleTime" class="u-form-item-row" borderBottom
115 134
                         @click="clickRecycleTimeRow">
116 135
                         <FormSelectToPage :val="formData.recycleTime" @deleteItem.stop="clear('recycleTime')">
117 136
                         </FormSelectToPage>
@@ -160,6 +179,11 @@
160 179
                                 @delete="deleteProductCard" name="1" multiple :maxCount="1" accept="image"></u-upload>
161 180
                         </view>
162 181
                     </u-form-item>
182
+                    <u-form-item label="付款方式" borderBottom>
183
+                        <TabSelect :tabList="paymentTabList" :colNum="4" mode="single"
184
+                            @tabChange="handlePaymentTabChange">
185
+                        </TabSelect>
186
+                    </u-form-item>
163 187
                 </u--form>
164 188
             </view>
165 189
 
@@ -171,17 +195,17 @@
171 195
     </view>
172 196
 </template>
173 197
 <script>
174
-import TabRadio from '@/components/custom-tab-radio/index.vue'
198
+import TabSelect from '@/components/custom-tab-select/index.vue'
175 199
 import FormSelectToPage from '@/components/form-select-to-page/index.vue'
176 200
 export default {
177 201
     components: {
178
-        TabRadio,
202
+        TabSelect,
179 203
         FormSelectToPage,
180 204
     },
181 205
     data() {
182 206
         return {
183 207
             checkboxValue: [],
184
-
208
+            recognitionContent: '',
185 209
             formData: {
186 210
                 imgs: [],
187 211
                 desc: '',
@@ -197,12 +221,13 @@ export default {
197 221
                 price: '',
198 222
                 productCondition: '',
199 223
                 productNo: '',
200
-                stock: 1,
224
+                stock: null,
201 225
                 costPrice: '',
202 226
                 samePrice: '',
203 227
                 agentPrice: '',
204 228
                 salePrice: '',
205 229
                 productPosition: '',
230
+                watchYear: '',
206 231
                 identifyingPerson: '',
207 232
                 recycleType: '',
208 233
                 recyclePerson: '',
@@ -215,6 +240,7 @@ export default {
215 240
                 productTag: '',
216 241
                 productAttachment: '',
217 242
                 productDesc: '',
243
+                paymentType: '',
218 244
             },
219 245
             rules: {
220 246
                 imgs: [
@@ -244,7 +270,6 @@ export default {
244 270
 
245 271
             },
246 272
             recycleTimeShow: false,
247
-            descPlaceholder: '95新 WHZ19219H CHANEL香奈儿链条单肩包 21开 牛皮 尺寸25 4 15 配件中溯卡',
248 273
             titlePlaceholder: '如不填,自动截取商品描述前50字',
249 274
             typeList: [
250 275
                 {
@@ -322,6 +347,32 @@ export default {
322 347
                     value: '4',
323 348
                 },
324 349
             ],
350
+            paymentTabList: [
351
+                {
352
+                    name: '微信',
353
+                    value: 1,
354
+                },
355
+                {
356
+                    name: '支付宝',
357
+                    value: 2,
358
+                },
359
+                {
360
+                    name: '银行卡',
361
+                    value: 3,
362
+                },
363
+                {
364
+                    name: '现金',
365
+                    value: 4,
366
+                },
367
+                {
368
+                    name: '数字货币',
369
+                    value: 5,
370
+                },
371
+                {
372
+                    name: '挂账',
373
+                    value: 6,
374
+                },
375
+            ],
325 376
             brandToUrl: '/pages/wareHouse/brandList',
326 377
             // 上传
327 378
             goodPicFileList: [{ url: 'https://uviewui.com/swiper/1.jpg' }],//商品图片
@@ -333,25 +384,45 @@ export default {
333 384
         }
334 385
     },
335 386
     methods: {
387
+        submitForm() {
388
+            this.$refs.addForm.validate().then((valid) => {
389
+                if (valid) {
390
+                    console.log('表单校验通过');
391
+                } else {
392
+                    console.log('表单校验不通过');
393
+                }
394
+            });
395
+        },
336 396
         handleTabChange(e) {
337 397
             console.log(e);
338 398
         },
339 399
         clear(key) {
340 400
             this.formData[key] = '';
341 401
         },
402
+        // 商品分类
403
+        handleTabChangeType(e) {
404
+            this.formData.type = e;
405
+            console.log(e, this.formData.type);
406
+            this.$refs.addForm.validateField('type')
407
+        },
342 408
         // 商品成色
343 409
         handleTabChangeProductCondition(e) {
344
-            console.log(e);
410
+            this.formData.productCondition = e;
411
+            this.$refs.addForm.validateField('productCondition')
345 412
         },
346 413
         // 商品属性
347 414
         handleTabChangeProductAttribute(e) {
348
-            console.log(e);
415
+            this.formData.productAttribute = e;
416
+            this.$refs.addForm.validateField('productAttribute')
349 417
         },
350 418
         // 回收类型
351 419
         handleTabChangeRecycleType(e) {
420
+            this.formData.recycleType = e;
421
+        },
422
+        // 付款方式
423
+        handlePaymentTabChange(e) {
352 424
             console.log(e);
353 425
         },
354
-
355 426
         clickRecycleTimeRow() {
356 427
             this.recycleTimeShow = true;
357 428
         },
@@ -435,6 +506,24 @@ export default {
435 506
             console.log(event);
436 507
             // this.fileList5 = [...this.fileList5, ...event.fileList];
437 508
         },
509
+        async handleRecognition() {
510
+            // 品牌:浪琴
511
+            // 来源:【麒麟】私信-杰3-3
512
+            // 实价:6500
513
+            // 型号:L2.257.5.89.7
514
+            // 编码:52356065
515
+            // 日期:2021.11.09
516
+            // 备注:全套
517
+            // 付款方式:线上
518
+            if (!this.recognitionContent) {
519
+                return;
520
+            }
521
+            try {
522
+                uni.$u.toast("识别成功");
523
+            } catch (e) {
524
+                uni.$u.toast("文本识别异常");
525
+            }
526
+        },
438 527
     }
439 528
 }
440 529
 </script>

+ 66 - 64
pages/wareHouse/brandList.vue

@@ -10,7 +10,8 @@
10 10
             <u-search placeholder="搜索" v-model="keyword"></u-search>
11 11
             <view class="suggest_list">
12 12
                 <view class="brand_item" v-for="item in brandList" :key="item.id">
13
-                    <img class="brand_img" :src="item.url" alt="">
13
+                    <img class="brand_img" v-if="item.url" :src="item.url" alt="">
14
+                    <img class="brand_img" v-else src="/static/no-img.png"></img>
14 15
                     <view class="brand_name">{{ item.name }}</view>
15 16
                 </view>
16 17
             </view>
@@ -25,7 +26,8 @@
25 26
                     <u-index-anchor :text="indexList[index]"></u-index-anchor>
26 27
                     <!-- #endif -->
27 28
                     <view class="list-cell" v-for="(cell, index) in item">
28
-                        <img :src="cell.url" alt="">
29
+                        <img v-if="cell.url" :src="cell.url" alt="">
30
+                        <img v-else src="/static/no-img.png"></img>
29 31
                         {{ cell.name }}
30 32
                     </view>
31 33
                 </u-index-item>
@@ -49,311 +51,311 @@ export default {
49 51
             brandList: [
50 52
                 {
51 53
                     id: 1,
52
-                    name: '品牌1',
54
+                    name: 'LOUIS VUITTON',
53 55
                     code: '001',
54
-                    url: './imgs/1.jpg',
56
+                    url: require('./imgs/lv.jpg'),
55 57
                 },
56 58
                 {
57 59
                     id: 2,
58 60
                     name: '品牌2',
59 61
                     code: '002',
60
-                    url: './imgs/1.jpg',
62
+                    url: null,
61 63
                 },
62 64
                 {
63 65
                     id: 1,
64 66
                     name: '品牌1',
65 67
                     code: '001',
66
-                    url: './imgs/1.jpg',
68
+                    url: null,
67 69
                 },
68 70
                 {
69 71
                     id: 2,
70 72
                     name: '品牌2',
71 73
                     code: '002',
72
-                    url: './imgs/1.jpg',
74
+                    url: null,
73 75
                 },
74 76
                 {
75 77
                     id: 1,
76 78
                     name: '品牌1',
77 79
                     code: '001',
78
-                    url: './imgs/1.jpg',
80
+                    url: null,
79 81
                 },
80 82
                 {
81 83
                     id: 1,
82 84
                     name: '品牌1',
83 85
                     code: '001',
84
-                    url: './imgs/1.jpg',
86
+                    url: null,
85 87
                 },
86 88
             ],
87 89
             indexList: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z","#"],
88 90
             itemArr: [
89 91
                 [
90 92
                     {
91
-                        name:'品牌1',
92
-                        url:require('./imgs/1.jpg'),
93
+                        name:'LOUIS VUITTON',
94
+                        url:require('./imgs/lv.jpg'),
93 95
                     },
94 96
                     {
95 97
                         name:'品牌2',
96
-                        url:'./imgs/1.jpg',
98
+                        url:null,
97 99
                     },
98 100
                 ],
99 101
                 [
100 102
                     {
101 103
                         name:'品牌3',
102
-                        url:'./imgs/1.jpg',
104
+                        url:null,
103 105
                     },
104 106
                     {
105 107
                         name:'品牌4',
106
-                        url:'./imgs/1.jpg',
108
+                        url:null,
107 109
                     },
108 110
                 ],
109 111
                 [
110 112
                     {
111 113
                         name:'品牌5',
112
-                        url:'./imgs/1.jpg',
114
+                        url:null,
113 115
                     },
114 116
                     {
115 117
                         name:'品牌6',
116
-                        url:'./imgs/1.jpg',
118
+                        url:null,
117 119
                     },
118 120
                 ],
119 121
                 [
120 122
                     {
121 123
                         name:'品牌7',
122
-                        url:'./imgs/1.jpg',
124
+                        url:null,
123 125
                     },
124 126
                     {
125 127
                         name:'品牌8',
126
-                        url:'./imgs/1.jpg',
128
+                        url:null,
127 129
                     },
128 130
                 ],
129 131
                 [
130 132
                     {
131 133
                         name:'品牌9',
132
-                        url:'./imgs/1.jpg',
134
+                        url:null,
133 135
                     },
134 136
                     {
135 137
                         name:'品牌10',
136
-                        url:'./imgs/1.jpg',
138
+                        url:null,
137 139
                     },
138 140
                 ],
139 141
                 [
140 142
                     {
141 143
                         name:'品牌11',
142
-                        url:'./imgs/1.jpg',
144
+                        url:null,
143 145
                     },
144 146
                     {
145 147
                         name:'品牌12',
146
-                        url:'./imgs/1.jpg',
148
+                        url:null,
147 149
                     },
148 150
                 ],
149 151
                 [
150 152
                     {
151 153
                         name:'品牌13',
152
-                        url:'./imgs/1.jpg',
154
+                        url:null,
153 155
                     },
154 156
                     {
155 157
                         name:'品牌14',
156
-                        url:'./imgs/1.jpg',
158
+                        url:null,
157 159
                     },
158 160
                 ],
159 161
                 [
160 162
                     {
161 163
                         name:'品牌15',
162
-                        url:'./imgs/1.jpg',
164
+                        url:null,
163 165
                     },
164 166
                     {
165 167
                         name:'品牌16',
166
-                        url:'./imgs/1.jpg',
168
+                        url:null,
167 169
                     },
168 170
                 ],
169 171
                 [
170 172
                     {
171 173
                         name:'品牌17',
172
-                        url:'./imgs/1.jpg',
174
+                        url:null,
173 175
                     },
174 176
                     {
175 177
                         name:'品牌18',
176
-                        url:'./imgs/1.jpg',
178
+                        url:null,
177 179
                     },
178 180
                 ],
179 181
                 [
180 182
                     {
181 183
                         name:'品牌19',
182
-                        url:'./imgs/1.jpg',
184
+                        url:null,
183 185
                     },
184 186
                     {
185 187
                         name:'品牌20',
186
-                        url:'./imgs/1.jpg',
188
+                        url:null,
187 189
                     },
188 190
                 ],
189 191
                 [
190 192
                     {
191 193
                         name:'品牌21',
192
-                        url:'./imgs/1.jpg',
194
+                        url:null,
193 195
                     },
194 196
                     {
195 197
                         name:'品牌22',
196
-                        url:'./imgs/1.jpg',
198
+                        url:null,
197 199
                     },
198 200
                 ],
199 201
                 [
200 202
                     {
201 203
                         name:'品牌23',
202
-                        url:'./imgs/1.jpg',
204
+                        url:null,
203 205
                     },
204 206
                     {
205 207
                         name:'品牌24',
206
-                        url:'./imgs/1.jpg',
208
+                        url:null,
207 209
                     },
208 210
                 ],
209 211
                 [
210 212
                     {
211 213
                         name:'品牌25',
212
-                        url:'./imgs/1.jpg',
214
+                        url:null,
213 215
                     },
214 216
                     {
215 217
                         name:'品牌26',
216
-                        url:'./imgs/1.jpg',
218
+                        url:null,
217 219
                     },
218 220
                 ],
219 221
                 [
220 222
                     {
221 223
                         name:'品牌27',
222
-                        url:'./imgs/1.jpg',
224
+                        url:null,
223 225
                     },
224 226
                     {
225 227
                         name:'品牌28',
226
-                        url:'./imgs/1.jpg',
228
+                        url:null,
227 229
                     },
228 230
                 ],
229 231
                 [
230 232
                     {
231 233
                         name:'品牌25',
232
-                        url:'./imgs/1.jpg',
234
+                        url:null,
233 235
                     },
234 236
                     {
235 237
                         name:'品牌26',
236
-                        url:'./imgs/1.jpg',
238
+                        url:null,
237 239
                     },
238 240
                 ],
239 241
                 [
240 242
                     {
241 243
                         name:'品牌27',
242
-                        url:'./imgs/1.jpg',
244
+                        url:null,
243 245
                     },
244 246
                     {
245 247
                         name:'品牌28',
246
-                        url:'./imgs/1.jpg',
248
+                        url:null,
247 249
                     },
248 250
                 ],
249 251
                 [
250 252
                     {
251 253
                         name:'品牌25',
252
-                        url:'./imgs/1.jpg',
254
+                        url:null,
253 255
                     },
254 256
                     {
255 257
                         name:'品牌26',
256
-                        url:'./imgs/1.jpg',
258
+                        url:null,
257 259
                     },
258 260
                 ],
259 261
                 [
260 262
                     {
261 263
                         name:'品牌27',
262
-                        url:'./imgs/1.jpg',
264
+                        url:null,
263 265
                     },
264 266
                     {
265 267
                         name:'品牌28',
266
-                        url:'./imgs/1.jpg',
268
+                        url:null,
267 269
                     },
268 270
                 ],
269 271
                 [
270 272
                     {
271 273
                         name:'品牌25',
272
-                        url:'./imgs/1.jpg',
274
+                        url:null,
273 275
                     },
274 276
                     {
275 277
                         name:'品牌26',
276
-                        url:'./imgs/1.jpg',
278
+                        url:null,
277 279
                     },
278 280
                 ],
279 281
                 [
280 282
                     {
281 283
                         name:'品牌27',
282
-                        url:'./imgs/1.jpg',
284
+                        url:null,
283 285
                     },
284 286
                     {
285 287
                         name:'品牌28',
286
-                        url:'./imgs/1.jpg',
288
+                        url:null,
287 289
                     },
288 290
                 ],
289 291
                 [
290 292
                     {
291 293
                         name:'品牌25',
292
-                        url:'./imgs/1.jpg',
294
+                        url:null,
293 295
                     },
294 296
                     {
295 297
                         name:'品牌26',
296
-                        url:'./imgs/1.jpg',
298
+                        url:null,
297 299
                     },
298 300
                 ],
299 301
                 [
300 302
                     {
301 303
                         name:'品牌27',
302
-                        url:'./imgs/1.jpg',
304
+                        url:null,
303 305
                     },
304 306
                     {
305 307
                         name:'品牌28',
306
-                        url:'./imgs/1.jpg',
308
+                        url:null,
307 309
                     },
308 310
                 ],
309 311
                 [
310 312
                     {
311 313
                         name:'品牌25',
312
-                        url:'./imgs/1.jpg',
314
+                        url:null,
313 315
                     },
314 316
                     {
315 317
                         name:'品牌26',
316
-                        url:'./imgs/1.jpg',
318
+                        url:null,
317 319
                     },
318 320
                 ],
319 321
                 [
320 322
                     {
321 323
                         name:'品牌27',
322
-                        url:'./imgs/1.jpg',
324
+                        url:null,
323 325
                     },
324 326
                     {
325 327
                         name:'品牌28',
326
-                        url:'./imgs/1.jpg',
328
+                        url:null,
327 329
                     },
328 330
                 ],
329 331
                 [
330 332
                     {
331 333
                         name:'品牌25',
332
-                        url:'./imgs/1.jpg',
334
+                        url:null,
333 335
                     },
334 336
                     {
335 337
                         name:'品牌26',
336
-                        url:'./imgs/1.jpg',
338
+                        url:null,
337 339
                     },
338 340
                 ],
339 341
                 [
340 342
                     {
341 343
                         name:'品牌27',
342
-                        url:'./imgs/1.jpg',
344
+                        url:null,
343 345
                     },
344 346
                     {
345 347
                         name:'品牌28',
346
-                        url:'./imgs/1.jpg',
348
+                        url:null,
347 349
                     },
348 350
                 ],
349 351
                 [
350 352
                     {
351 353
                         name:'##品牌27',
352
-                        url:'./imgs/1.jpg',
354
+                        url:null,
353 355
                     },
354 356
                     {
355 357
                         name:'#品牌28',
356
-                        url:'./imgs/1.jpg',
358
+                        url:null,
357 359
                     },
358 360
                 ]
359 361
             ]

+ 7 - 1
pages/wareHouse/detail.vue

@@ -158,7 +158,7 @@
158 158
                 <i class="iconfont icon-crm-dayin" style="font-size:46rpx;color: #9ca3af;"></i>
159 159
                 <text class="bar-text">打印</text>
160 160
             </view>
161
-            <view class="bar-item">
161
+            <view class="bar-item" @click="handleOpenOrder">
162 162
                 <view class="primary">
163 163
                     <u-icon name="bag" size="44rpx" color="#fff"></u-icon>
164 164
                     <text class="bar-text">开单</text>
@@ -229,6 +229,12 @@
229 229
             }
230 230
         },
231 231
         methods: {
232
+            // 打开销售业务开单页面
233
+            handleOpenOrder() {
234
+                uni.navigateTo({
235
+                    url: '/pages/wareHouse/openOrder'
236
+                });
237
+            },
232 238
             // 查看操作日志的方法
233 239
             viewLog() {
234 240
                 // 查看操作日志的方法

BIN
pages/wareHouse/imgs/lv.jpg


+ 17 - 7
pages/wareHouse/index.vue

@@ -9,31 +9,28 @@
9 9
 						<view class="asset-title">总资产成本(元)</view>
10 10
 						<u-icon name="question-circle" size="14" color="#999999"></u-icon>
11 11
 					</view>
12
-					<text class="asset-value">3,869,014</text>
12
+					<text class="asset-value">{{ wareHouseCard.totalCost }}</text>
13 13
 				</view>
14 14
 				<u-button class="view-btn" type="text" size="mini">查看财务报表</u-button>
15 15
 			</view>
16 16
 			<view class="data-cards">
17 17
 				<view class="card-item">
18 18
 					<text class="card-label">今日上传</text>
19
-					<text class="card-value">12</text>
19
+					<text class="card-value">{{ wareHouseCard.uploadCostToday }}</text>
20 20
 				</view>
21 21
 				<view class="card-item">
22 22
 					<text class="card-label">今日下架</text>
23
-					<text class="card-value green">8</text>
23
+					<text class="card-value green">{{ wareHouseCard.outStockToday }}</text>
24 24
 				</view>
25 25
 				<view class="card-item">
26 26
 					<text class="card-label">商品总数</text>
27
-					<text class="card-value">2</text>
27
+					<text class="card-value">{{ wareHouseCard.totalNum }}</text>
28 28
 				</view>
29 29
 			</view>
30 30
 
31 31
 			<view class="search-wrapper">
32 32
 				<u-search placeholder="搜索编号、名称、品牌..." bg-color="#f9fafb" border-radius="4rpx"
33 33
 					:show-action="false" class="search-input-wrap"></u-search>
34
-				<view class="search-filter-btn">
35
-					<u-icon name="list" size="22" color="#666666"></u-icon>
36
-				</view>
37 34
 			</view>
38 35
 
39 36
 			<view class="category-tabs-wrap">
@@ -55,6 +52,7 @@
55 52
 
56 53
 					<view class="layout-btn" type="text" size="mini">
57 54
 						<u-icon name="grid" size="20" color="#666666"></u-icon>
55
+						<!-- 筛选列 品牌、价格范围、位置、回收时间、回收人员、鉴定人员、商品属性 -->
58 56
 					</view>
59 57
 				</view>
60 58
 			</view>
@@ -122,6 +120,7 @@
122 120
 export default {
123 121
 	data() {
124 122
 		return {
123
+			wareHouseCard:{},
125 124
 			tabList: [
126 125
 				{ name: "全部" },
127 126
 				{ name: "腕表" },
@@ -202,6 +201,17 @@ export default {
202 201
 				url: `/pages/wareHouse/add`
203 202
 			});
204 203
 		},
204
+		// 获取仓库卡片数据
205
+		getCard() {
206
+			uni.$u.api.getWareHouseCard().then(res => {
207
+				if (res.code === 200) {
208
+					this.wareHouseCard = res.data;
209
+				}
210
+			});
211
+		},
212
+	},
213
+	mounted() {
214
+		this.getCard();
205 215
 	}
206 216
 };
207 217
 </script>

+ 246 - 0
pages/wareHouse/openOrder.vue

@@ -0,0 +1,246 @@
1
+<template>
2
+   <view class="open_order" @click="handleClickOutside">
3
+      <u-navbar class="nav-bar" title="销售业务开单" :autoBack="true" :placeholder="true" v-hideNav></u-navbar>
4
+      <view class="open_order_content">
5
+         <view class="header">
6
+            <img :src="openOrderForm.url" alt="">
7
+            <view class="header_box">
8
+               <view class="title">
9
+                  {{ openOrderForm.title }} | {{ openOrderForm.desc }}
10
+               </view>
11
+               <view class="header_detail_box">
12
+                  <view class="total_cost">
13
+                     <view class="total_cost_title">系统总成本</view>
14
+                     <view class="total_cost_price">¥{{ openOrderForm.totalCost }}</view>
15
+                  </view>
16
+                  <view class="advice_price">
17
+                     <view class="advice_price_title">建议标价</view>
18
+                     <view class="advice_price_price">¥{{ openOrderForm.advicePrice }}</view>
19
+                  </view>
20
+               </view>
21
+            </view>
22
+         </view>
23
+         <u--form labelPosition="top" :model="openOrderForm" :rules="rules" ref="openOrderForm" label-width="200rpx">
24
+            <view class="card_item">
25
+               <u-form-item label="成交金额" required prop="price">
26
+                  ¥<u--input v-model="openOrderForm.price" border="none" type="number"></u--input>
27
+               </u-form-item>
28
+            </view>
29
+            <view class="card_item">
30
+               <u-form-item label="开单数量">
31
+                  <u-number-box v-model="openOrderForm.quantity"></u-number-box>
32
+               </u-form-item>
33
+            </view>
34
+            <view class="card_item">
35
+               <u-form-item label="订单类型">
36
+                  <TabSelect :tabList="tabList" mode="multiple" :colNum="4" :defaultIndex="1"
37
+                     @tabChange="changeOrderType">
38
+                  </tabSelect>
39
+               </u-form-item>
40
+            </view>
41
+            <view class="card_item">
42
+               <u-form-item label="销售人员与时间" class="sales_person_box_form">
43
+                  <view class="sales_person_box" @click="personShow = true">
44
+                     <u-icon name="man-add" size="36rpx" color="#374151"></u-icon>
45
+                     <view class="text">{{ openOrderForm.salesPerson }}</view>
46
+                  </view>
47
+                  <view class="sales_person_box" @click="dateShow = true">
48
+                     <u-icon name="calendar" size="36rpx" color="#374151"></u-icon>
49
+                     <view class="text">{{ openOrderForm.date }}</view>
50
+                  </view>
51
+
52
+               </u-form-item>
53
+            </view>
54
+            <view class="card_item">
55
+               <u-form-item label="收款方式">
56
+                  <TabSelect :tabList="paymentTabList" mode="single" :colNum="4" :defaultIndex="1"
57
+                     @tabChange="changePaymentTab">
58
+                  </tabSelect>
59
+               </u-form-item>
60
+            </view>
61
+            <view class="card_item">
62
+               <u-form-item label="售后保障配置">
63
+                  <TabSelect :tabList="afterSaleTabList" mode="multiple" :colNum="3" :defaultIndex="1"
64
+                     @tabChange="changeAfterSaleTab">
65
+                  </tabSelect>
66
+               </u-form-item>
67
+            </view>
68
+            <view class="card_item">
69
+               <u-form-item label="支付凭证上传">
70
+                  <u-upload :fileList="paymentProof" @afterRead="afterReadPaymentProof" @delete="deletePaymentProof"
71
+                     name="1" multiple :maxCount="10"></u-upload>
72
+               </u-form-item>
73
+            </view>
74
+            <view class="card_item">
75
+               <u-form-item label="订单备注">
76
+                  <u--textarea v-model="openOrderForm.remark" placeholder="请输入订单备注" confirmType="done"></u--textarea>
77
+               </u-form-item>
78
+            </view>
79
+            <view class="card_item">
80
+               <u-form-item label="收货地址">
81
+                  <u--textarea v-model="openOrderForm.address" placeholder="请输入收货地址" confirmType="done"></u--textarea>
82
+               </u-form-item>
83
+            </view>
84
+         </u--form>
85
+      </view>
86
+      <view class="bottom_box">
87
+         <view class="bottom_box_item">
88
+            <view class="bottom_box_item_title">实收总计</view>
89
+            <view class="bottom_box_item_price">¥{{ openOrderForm.amountReceived }}</view>
90
+         </view>
91
+         <u-button color="#3c9cff" type="primary" @click="submitForm"  icon="checkmark">确认开单</u-button>
92
+      </view>
93
+      <u-popup :show="personShow" @close="close" @open="open">
94
+         人员选择
95
+      </u-popup>
96
+      <u-datetime-picker :show="dateShow" v-model="openOrderForm.date" mode="date" @confirm="confirmDate"
97
+         @close="closeDate" @cancel="closeDate"></u-datetime-picker>
98
+   </view>
99
+</template>
100
+<script>
101
+import TabSelect from '@/components/custom-tab-select/index.vue'
102
+export default {
103
+   components: {
104
+      TabSelect,
105
+   },
106
+   data() {
107
+      return {
108
+         openOrderForm: {
109
+            url: require('./imgs/1.jpg'),
110
+            title: 'ROLEX',
111
+            desc: 'SUBMSRINER DATE 126610LN',
112
+            totalCost: '82500',
113
+            advicePrice: '890000',
114
+            price: null,
115
+            quantity: 1,
116
+            salesPerson: 'IT秦',
117
+            orderType: [],
118
+            date: '2026-1-1',
119
+            paymentTab: 1,
120
+            afterSaleTab: [],
121
+            remark: '',
122
+            address: '',
123
+            amountReceived: 89000,
124
+         },
125
+         paymentProof: [],
126
+         tabList: [
127
+            {
128
+               name: '零售',
129
+               value: 1,
130
+            },
131
+            {
132
+               name: '寄卖',
133
+               value: 2,
134
+            },
135
+            {
136
+               name: '同行',
137
+               value: 3,
138
+            },
139
+            {
140
+               name: '退货',
141
+               value: 4,
142
+            },
143
+            {
144
+               name: '质押',
145
+               value: 5,
146
+            },
147
+         ],
148
+         paymentTabList: [
149
+            {
150
+               name: '微信',
151
+               value: 1,
152
+            },
153
+            {
154
+               name: '支付宝',
155
+               value: 2,
156
+            },
157
+            {
158
+               name: '银行卡',
159
+               value: 3,
160
+            },
161
+            {
162
+               name: '现金',
163
+               value: 4,
164
+            },
165
+            {
166
+               name: '数字货币',
167
+               value: 5,
168
+            },
169
+            {
170
+               name: '挂账',
171
+               value: 6,
172
+            },
173
+         ],
174
+         afterSaleTabList: [
175
+            {
176
+               name: '假一赔三',
177
+               value: 1,
178
+            },
179
+            {
180
+               name: '一年质保',
181
+               value: 2,
182
+            },
183
+            {
184
+               name: '一年内八折回收',
185
+               value: 3,
186
+            },
187
+            {
188
+               name: '送保养一次',
189
+               value: 4,
190
+            },
191
+            {
192
+               name: '原厂配件保证',
193
+               value: 5,
194
+            },
195
+         ],
196
+         rules: {
197
+            price: [
198
+               { required: true, message: '请输入成交金额', trigger: ['blur'] },
199
+            ],
200
+         },
201
+         personShow: false,
202
+         dateShow: false,
203
+      }
204
+   },
205
+   methods: {
206
+      changeOrderType(val) {
207
+         this.openOrderForm.orderType = val
208
+      },
209
+      changePaymentTab(val) {
210
+         this.openOrderForm.paymentTab = val
211
+      },
212
+      changeAfterSaleTab(val) {
213
+         this.openOrderForm.afterSaleTab = val
214
+      },
215
+      handleClickOutside() {
216
+         this.personShow = false
217
+      },
218
+      confirmDate(val) {
219
+         this.openOrderForm.date = this.$dayjs(val.value).format('YYYY-MM-DD');
220
+         console.log(this.openOrderForm.date);
221
+
222
+         this.dateShow = false
223
+      },
224
+      closeDate() {
225
+         this.dateShow = false
226
+      },
227
+      afterReadPaymentProof(file) {
228
+         // this.paymentProof.push(file)
229
+      },
230
+      deletePaymentProof(index) {
231
+         // this.paymentProof.splice(index, 1)
232
+      },
233
+      submitForm() {
234
+         this.$refs.openOrderForm.validate().then(res => {
235
+            if (res) {
236
+               console.log('提交成功', this.openOrderForm);
237
+               
238
+            }
239
+         })
240
+      },
241
+   }
242
+}
243
+</script>
244
+<style lang="scss" scoped>
245
+@import './styles/openOrder.scss';
246
+</style>

+ 6 - 0
pages/wareHouse/styles/add.scss

@@ -47,4 +47,10 @@
47 47
             }
48 48
         }
49 49
     }
50
+    &.u-form-item-col {
51
+        .u-form-item__body__right__content__slot {
52
+            flex-direction: column !important;
53
+            align-items: normal !important;
54
+        }
55
+    }
50 56
 }

+ 174 - 0
pages/wareHouse/styles/openOrder.scss

@@ -0,0 +1,174 @@
1
+.open_order {
2
+    .open_order_content {
3
+        margin-bottom:150rpx;
4
+        .header {
5
+            display: flex;
6
+            justify-content: flex-start;
7
+            align-items: flex-start;
8
+            padding: 20rpx;
9
+            background-color: #1f2937;
10
+            border-radius: 20rpx;
11
+            margin: 20rpx;
12
+
13
+            img {
14
+                width: 150rpx;
15
+                height: 150rpx;
16
+                border-radius: 20rpx;
17
+                flex-shrink: 0;
18
+            }
19
+
20
+            .header_box {
21
+                display: flex;
22
+                flex-direction: column;
23
+                align-items: flex-start;
24
+                padding: 0 20rpx;
25
+                flex: 1;
26
+                min-width: 0;
27
+
28
+                .title {
29
+                    font-size: 32rpx;
30
+                    font-weight: 600;
31
+                    color: #ffffff;
32
+                    display: -webkit-box;
33
+                    -webkit-line-clamp: 1;
34
+                    -webkit-box-orient: vertical;
35
+                    overflow: hidden;
36
+                    text-overflow: ellipsis;
37
+                    line-height: 1.4;
38
+                    word-break: break-word;
39
+                    width: 100%;
40
+                }
41
+
42
+                .header_detail_box {
43
+                    display: flex;
44
+                    justify-content: space-between;
45
+                    align-items: center;
46
+                    padding: 20rpx 0;
47
+                    width: 100%;
48
+
49
+                    .total_cost {
50
+                        display: flex;
51
+                        flex-direction: column;
52
+                        align-items: flex-start;
53
+                        padding: 20rpx 0;
54
+                        color: #ffffff;
55
+                        font-size: 24rpx;
56
+
57
+                        .total_cost_title {
58
+                            color: #838a97;
59
+                            font-size: 24rpx;
60
+                        }
61
+
62
+                        .total_cost_price {
63
+                            color: #ffffff;
64
+                            font-size: 30rpx;
65
+                        }
66
+                    }
67
+
68
+                    .advice_price {
69
+                        display: flex;
70
+                        flex-direction: column;
71
+                        align-items: flex-end;
72
+                        padding: 20rpx 0;
73
+                        color: #ffffff;
74
+                        font-size: 24rpx;
75
+
76
+                        .advice_price_title {
77
+                            color: #838a97;
78
+                            font-size: 24rpx;
79
+                        }
80
+
81
+                        .advice_price_price {
82
+                            color: #d0a10d;
83
+                            font-size: 30rpx;
84
+                            font-weight: 600;
85
+                        }
86
+                    }
87
+                }
88
+            }
89
+
90
+        }
91
+
92
+        .card_item {
93
+            display: flex;
94
+            flex-direction: column;
95
+            align-items: flex-start;
96
+            background-color: #ffffff;
97
+            border-radius: 20rpx;
98
+            padding: 20rpx;
99
+            margin:10rpx 20rpx;
100
+
101
+            font-weight: 600;
102
+
103
+
104
+
105
+            ::v-deep .u-form-item {
106
+                width: 100%;
107
+
108
+                .u-form-item__body__left__content__label {
109
+                    color: #9ca3af;
110
+                    font-size: 24rpx;
111
+                }
112
+
113
+                .u-form-item__body__right {
114
+                    color: #000;
115
+                    font-size: 40rpx;
116
+
117
+                    .uni-input-wrapper {
118
+                        font-size: 40rpx;
119
+                    }
120
+                }
121
+            }
122
+
123
+            ::v-deep .sales_person_box_form {
124
+                .u-form-item__body__right__content__slot {
125
+                    display: grid;
126
+                    grid-template-columns: 1fr 2fr;
127
+                    gap: 20rpx;
128
+
129
+                    .sales_person_box {
130
+                        display: flex;
131
+                        gap: 10rpx;
132
+                        justify-content: flex-start;
133
+                        align-items: center;
134
+                        padding: 10rpx 20rpx;
135
+                        border-radius: 10rpx;
136
+                        background-color: #f3f4f6;
137
+
138
+                        .text {
139
+                            font-size: 26rpx;
140
+                            font-weight: 600;
141
+                            color: #374151;
142
+                        }
143
+                    }
144
+                }
145
+            }
146
+        }
147
+    }
148
+    .bottom_box{
149
+        position:fixed;
150
+        bottom:0;
151
+        left:0;
152
+        right:0;
153
+        display: grid;
154
+        grid-template-columns: 1fr 2fr;
155
+        gap: 20rpx;
156
+        padding: 20rpx;
157
+        background-color: #ffffff;
158
+        .bottom_box_item{
159
+            display: flex;
160
+            flex-direction: column;
161
+            align-items: flex-start;
162
+            font-weight: 600;
163
+            color: #9ca3af;
164
+            .bottom_box_item_title{
165
+                font-size: 24rpx;
166
+            }
167
+            .bottom_box_item_price{
168
+                font-size: 40rpx;
169
+                font-weight: 600;
170
+                color: #dc2626;
171
+            }
172
+        }
173
+    }
174
+}

BIN
static/no-img.png


+ 9 - 0
utils/api.js

@@ -114,6 +114,15 @@ const install = (Vue, vm) => {
114 114
 
115 115
 		// 支付相关接口
116 116
 		saveOrderFileAndTransfer:(data={})=>http.post(store.state.user.path + '/storeInfo/saveOrderFileAndTransfer',data),
117
+
118
+		// ========== Mock接口(开发环境使用,本地Mock服务器)==========
119
+		// 服务器地址: http://192.168.0.243:3001
120
+		// 手机预览时需要使用电脑局域网IP,不能用localhost
121
+		// 切换真实接口时,将 baseUrl 改为真实接口地址即可
122
+		getPersonCards:()=>http.get('http://192.168.0.243:3001/mock-api/prod-api/crm/getPersonCards'),
123
+		getPersonLatestClue:()=>http.get('http://192.168.0.243:3001/mock-api/prod-api/crm/getPersonLatestClue'),
124
+		getPersonRanking:()=>http.get('http://192.168.0.243:3001/mock-api/prod-api/crm/getPersonRanking'),
125
+		getWareHouseCard:()=>http.get('http://192.168.0.243:3001/mock-api/prod-api/crm/getWareHouseCard'),
117 126
 	}
118 127
 }
119 128
 

+ 6 - 1
utils/request.js

@@ -28,7 +28,12 @@ const install = (Vue, vm) => {
28 28
 		const { ip, port, folder } = store.state.user.netConfig;
29 29
 		const baseURL = ip + (port ? ":" + port : "") + folder; /* 根域名 */
30 30
 		// 处理请求url的逻辑
31
-		config.url = baseURL + config.url;
31
+		// 如果是完整的URL(包含http://或https://)或者是本地Mock服务器请求,则不拼接baseURL
32
+ 		const isFullUrl = /^https?:\/\//i.test(config.url);
33
+ 		const isMockRequest = config.url.includes('localhost:3001') || config.url.includes('192.168.0.243:3001');
34
+ 		if (!isFullUrl && !isMockRequest) {
35
+ 			config.url = baseURL + config.url;
36
+ 		}
32 37
 		
33 38
 		if(config.custom.loading){
34 39
 			const { loadingText } = config.custom;