index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. <template>
  2. <view class="content">
  3. <view class="title">
  4. 服务信息
  5. </view>
  6. <up-form :model="form" labelWidth="70" ref="uFormRef">
  7. <up-form-item v-if="form.isonlinesales || userType == 1" label="是否补贴" prop="isallowance">
  8. <up-radio-group v-model="form.isallowance">
  9. <up-radio :customStyle="{ marginLeft: '12px' }"
  10. v-for="(item) in [{ label: '补贴', value: 1 }, { label: '不补贴', value: 0 }]" :key="item.value"
  11. :label="item.label" :name="item.value">
  12. </up-radio>
  13. </up-radio-group>
  14. </up-form-item>
  15. <up-form-item v-if="userType == 1" label="网销工单" prop="isonlinesales">
  16. <up-radio-group v-model="form.isonlinesales">
  17. <up-radio :customStyle="{ marginLeft: '12px' }"
  18. v-for="(item) in [{ label: '是', value: 1 }, { label: '否', value: 0 }]" :key="item.value"
  19. :label="item.label" :name="item.value">
  20. </up-radio>
  21. </up-radio-group>
  22. </up-form-item>
  23. <up-form-item v-if="form.isonlinesales || userType == 1" label="指定服务商">
  24. <view class="picker" hover-class="navigator-hover" @click="selectServiceProvider">
  25. {{ serviceProviders.name || '选择指定的服务商进行服务' }}
  26. </view>
  27. </up-form-item>
  28. <up-form-item label="服务类型" :required="rules.servicetype[0].required" prop="servicetype">
  29. <up-radio-group v-model="form.servicetype" @change="servicetypeChange">
  30. <up-radio :customStyle="{ marginLeft: '12px' }" v-for="(item) in servertypes" :key="item"
  31. :label="item" :name="item">
  32. </up-radio>
  33. </up-radio-group>
  34. </up-form-item>
  35. <up-form-item label="产品品类" :required="rules.class1[0].required" prop="class1">
  36. <up-radio-group v-model="form.class1">
  37. <up-radio :customStyle="{ marginLeft: '12px' }" v-for="(item) in class1" :key="item.value"
  38. :label="item.value" :name="item.value">
  39. </up-radio>
  40. </up-radio-group>
  41. </up-form-item>
  42. <up-form-item v-if="rules.class2[0].required" label="故障类型" :required="rules.class2[0].required"
  43. prop="class2">
  44. <picker class="picker" mode="selector" :range="class2" range-key="value" @change="changeClass2">
  45. {{ form.class2 || '请选择故障类型' }}
  46. </picker>
  47. </up-form-item>
  48. <view class="title">
  49. 基础信息
  50. </view>
  51. <up-form-item label="序列号" :required="rules.sku[0].required" prop="sku">
  52. <up-input v-model="form.sku" placeholder="序列号" clearable @blur="skuConfirm">
  53. <template #suffix>
  54. <view style="display: flex;align-items: center;">
  55. <up-icon name="scan" color="#2979ff" size="28" @click="openScan" />
  56. </view>
  57. </template>
  58. </up-input>
  59. </up-form-item>
  60. <up-form-item label="保修状态" v-if="userType == 1" prop="warrantystatus">
  61. <up-radio-group v-model="form.warrantystatus">
  62. <up-radio :customStyle="{ marginLeft: '12px' }" v-for="(item) in [{ label: '保内' }, { label: '保外' }]"
  63. :key="item.label" :label="item.label" :name="item.label">
  64. </up-radio>
  65. </up-radio-group>
  66. </up-form-item>
  67. <up-form-item label="客户名称" :required="rules.scenecontact[0].required" prop="scenecontact">
  68. <up-input v-model="form.scenecontact" placeholder="客户名称" clearable />
  69. </up-form-item>
  70. <up-form-item label="手机号" :required="rules.scenecontactphonenumber[0].required"
  71. prop="scenecontactphonenumber">
  72. <up-input type="number" v-model="form.scenecontactphonenumber" placeholder="联系人电话" clearable>
  73. <template #suffix>
  74. <up-button type="success" :disabled="!form.scenecontactphonenumber" size="mini" text="查询带入客户信息"
  75. @click="phonenumberConfirm" />
  76. </template>
  77. </up-input>
  78. </up-form-item>
  79. <up-form-item label="省市县" :required="rules.province[0].required" prop="province">
  80. <picker class="picker" mode="region" :value="[form.province, form.city, form.county]"
  81. @change="changeRegion">
  82. {{ form.province ? [form.province, form.city, form.county].join("-") : '选择省市县' }}
  83. </picker>
  84. </up-form-item>
  85. <up-form-item label="详细地址" prop="address" :required="rules.address[0].required">
  86. <up-textarea maxlength="499" v-model="form.address" placeholder="详细地址" autoHeight height="20" />
  87. </up-form-item>
  88. <up-form-item label="" prop="remarks">
  89. <up-textarea v-model="form.remarks" placeholder="如有特殊需求,您可在此处留言" count></up-textarea>
  90. </up-form-item>
  91. </up-form>
  92. <view style="padding-bottom: 50px;width: 350rpx;margin: 40rpx auto 0;" @click="save">
  93. <My-button text="保存" :loading="loading" />
  94. </view>
  95. </view>
  96. <up-popup :show="products.length" @close="closePopup" :customStyle="{
  97. width: '80vw',
  98. }" mode="right">
  99. <scroll-view :safeAreaInsetBottom="false" scroll-y style="width: 100%;height: 100vh;">
  100. <view class="product" v-for="item in products" :key="item.itemid" hover-class="navigator-hover"
  101. @click="changeItem(item)">
  102. <view class="itemname">
  103. {{ item.itemname }}
  104. </view>
  105. <view class="row">
  106. 序列号: {{ item.sku || '--' }}
  107. </view>
  108. <view class="row">
  109. 产品型号: {{ item.model || '--' }}
  110. </view>
  111. <view class="row">
  112. 经销商: {{ item.enterprisename || '--' }}
  113. </view>
  114. <view class="row">
  115. 用户信息: {{ item.name || '--' }} {{ item.phonenumber || '--' }}
  116. </view>
  117. </view>
  118. <view style="height: 30px;" />
  119. </scroll-view>
  120. </up-popup>
  121. <up-popup :show="customers.length" @close="closeCustomers" :customStyle="{
  122. width: '80vw',
  123. }" mode="right">
  124. <scroll-view :safeAreaInsetBottom="false" scroll-y style="width: 100%;height: 100vh;">
  125. <view class="product" v-for="item in customers" :key="item.sa_customersid" hover-class="navigator-hover"
  126. @click="selectCustomer(item)">
  127. <view class="itemname">
  128. {{ item.name }}
  129. </view>
  130. <view class="row">
  131. 手机号: {{ item.phonenumber || '--' }}
  132. </view>
  133. <view class="row">
  134. 搜索项: {{ item.province + item.city + item.county || '--' }}
  135. </view>
  136. <view class="row">
  137. 详细地址: {{ item.address || '--' }}
  138. </view>
  139. </view>
  140. <view style="height: 30px;" />
  141. </scroll-view>
  142. </up-popup>
  143. </template>
  144. <script setup>
  145. import { ref, reactive, getCurrentInstance } from 'vue';
  146. const { $Http } = getCurrentInstance().proxy;
  147. import { onShow, onLoad } from '@dcloudio/uni-app';
  148. const userType = ref(uni.getStorageSync('userMsg').usertype || 0);
  149. const uFormRef = ref(null);
  150. const form = reactive({
  151. sa_serviceorderid: 0,
  152. sa_orderid: 0,
  153. servicetype: '安装', // 服务类型
  154. class1: '', // 产品品类
  155. class2: '', // 故障类型
  156. sku: '', // 序列号
  157. itemid: '', // 产品ID
  158. itemname: '', // 产品名称
  159. itemno: '', // 产品编号
  160. model: '', // 产品型号
  161. cardno: '', // 保修卡号
  162. scenecontact: '', // 联系人
  163. scenecontactphonenumber: '', // 联系人电话
  164. province: '', // 省
  165. city: '', // 市
  166. county: '', // 县
  167. address: '', // 详细地址
  168. remarks: '',
  169. sys_enterpriseid: '',
  170. customername: "", // 客户名称
  171. customerphonenumber: "", // 客户电话
  172. sa_customersid: 0,
  173. isonlinesales: 0, // 是否网销客户
  174. isallowance: 0, // 是否补贴
  175. warrantystatus: "", // 保修状态
  176. });
  177. //服务商
  178. const serviceProviders = ref({
  179. name: '',
  180. id: ''
  181. });
  182. function selectServiceProvider() {
  183. uni.navigateTo({
  184. url: '/pages/launchApplication/selectServiceProvider'
  185. });
  186. $Http.onSelectServiceProvider = (provider) => {
  187. serviceProviders.value.name = provider.enterprisename;
  188. serviceProviders.value.id = provider.sys_enterpriseid;
  189. console.log("选择服务商", serviceProviders.value);
  190. uni.navigateBack();
  191. $Http.onSelectServiceProvider = null;
  192. }
  193. }
  194. $Http.basic({
  195. "classname": "common.usercenter.usercenter",
  196. "method": "queryUserMsg",
  197. "content": {}
  198. }).then(res => {
  199. console.log("用户信息", res);
  200. if (res.code === 1) {
  201. form.sys_enterpriseid = res.data.hr.sys_enterpriseid;
  202. if (res.data.agent.type == '网销') {
  203. form.isonlinesales = 1;
  204. }
  205. // 在enterprise中取省市县
  206. form.province = res.data.enterprise.province;
  207. form.city = res.data.enterprise.city;
  208. form.county = res.data.enterprise.county;
  209. }
  210. })
  211. let customers = ref([]); // 客户列表
  212. function phonenumberConfirm() {
  213. $Http.basic({
  214. "id": 2025121118401503,
  215. "content": {
  216. "nocache": true,
  217. "pageNumber": 1,
  218. "pageSize": 10, "where": { "phonenumber": form.scenecontactphonenumber }
  219. }
  220. }).then(res => {
  221. console.log("根据电话查询客户信息", res)
  222. if (res.code !== 1) {
  223. return uni.showToast({ title: res.msg, icon: 'none' });
  224. }
  225. if (res.data.length === 0) {
  226. return uni.showToast({ title: '未查询到对应的客户信息', icon: 'none' });
  227. } else if (res.data.length === 1) {
  228. selectCustomer(res.data[0]);
  229. } else {
  230. customers.value = res.data;
  231. }
  232. })
  233. }
  234. function closeCustomers() {
  235. customers.value = [];
  236. }
  237. function selectCustomer(item) {
  238. let list = ['name', 'phonenumber', 'province', 'city', 'county', 'sa_customersid', 'address'];
  239. list.forEach(key => {
  240. if (key == 'name') {
  241. form['customername'] = item[key] || form['customername'] || '';
  242. form['scenecontact'] = item[key] || form['scenecontact'] || '';
  243. } else if (key == 'phonenumber') {
  244. form['customerphonenumber'] = item[key] || form['customerphonenumber'] || '';
  245. form['scenecontactphonenumber'] = item[key] || form['scenecontactphonenumber'] || '';
  246. } else if (['province', 'city', 'county'].includes(key)) {
  247. form[key] = item[key] || form[key] || '';
  248. } else {
  249. form[key] = item[key] || '';
  250. }
  251. });
  252. uni.showToast({ title: '客户信息已带入', icon: 'none' });
  253. closeCustomers();
  254. }
  255. const rules = reactive({
  256. servicetype: [{ required: true, message: '请选择服务类型', trigger: 'change' }],
  257. class1: [{ required: true, message: '请选择产品品类', trigger: 'change' }],
  258. class2: [{ required: false, message: "请选择故障类型", trigger: 'change' }],
  259. sku: [{ required: false, message: '请输入序列号', trigger: 'blur' }],
  260. itemno: [{ required: false, message: '请输入产品编号', trigger: 'blur' }],
  261. itemname: [{ required: true, message: '请选择产品', trigger: 'blur' }],
  262. model: [{ required: false, message: '请输入产品型号', trigger: 'blur' }],
  263. cardno: [{ required: false, message: '请选择保修卡号', trigger: 'blur' }],
  264. province: [{ required: true, message: '请选择省市县', trigger: 'change' }],
  265. address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
  266. customername: [{ required: false, disabled: true, message: '请输客户名称', trigger: 'blur' }],
  267. customerphonenumber: [{ required: false, message: '请输入客户电话', trigger: 'blur', pattern: /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/, message: '请输入正确的手机号码' }],
  268. scenecontact: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
  269. scenecontactphonenumber: [{ required: true, message: '请输入联系人电话', trigger: 'blur', pattern: /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/, message: '请输入正确的手机号码' }],
  270. });
  271. // 切换故障类型
  272. function changeClass2(e) {
  273. let index = e.detail.value - 0;
  274. form.class2 = class2.value[index].value;
  275. }
  276. // 切换服务类型
  277. function servicetypeChange(type) {
  278. rules.class2[0].required = type == '维修';
  279. uFormRef.value.setRules(rules);
  280. }
  281. const class1 = ref(''),
  282. servertypes = ref(['安装', '维修', '清洗']),
  283. class2 = ref('');
  284. onLoad((options) => {
  285. console.log(options)
  286. if (options.sku) {
  287. form.sku = options.sku;
  288. skuConfirm();
  289. }
  290. })
  291. onShow(() => {
  292. $Http.getClass('servertype').then(res => {
  293. if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
  294. servertypes.value = res.data.map(v => v.value);
  295. });
  296. $Http.getClass('prodclass1').then(res => {
  297. if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
  298. class1.value = res.data;
  299. });
  300. $Http.getClass('faulttype').then(res => {
  301. if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
  302. class2.value = res.data;
  303. uFormRef.value.setRules(rules);
  304. });
  305. });
  306. function changeRegion(e) {
  307. form.province = e.detail.value[0];
  308. form.city = e.detail.value[1];
  309. form.county = e.detail.value[2];
  310. }
  311. // 保存
  312. let loading = ref(false);
  313. let querySkuing = false;
  314. function save() {
  315. if (querySkuing) {
  316. return uni.showToast({ title: '正在查询产品信息,请稍后再试', icon: 'none' });
  317. }
  318. if (loading.value) return;
  319. uFormRef.value.validate().then(valid => {
  320. if (valid) wx.showModal({
  321. content: '请确认预约信息正确以便后续服务,是否确认提交?',
  322. title: '提示',
  323. success: ({ confirm }) => {
  324. if (confirm) {
  325. form.customername = form.scenecontact;
  326. form.customerphonenumber = form.scenecontactphonenumber;
  327. form.name = form.customername;
  328. form.phonenumber = form.scenecontactphonenumber;
  329. form.sa_customersid = form.sa_customersid || 0;
  330. form.sys_enterpriseid_service = serviceProviders.value.id || 0;
  331. form.sys_enterpriseid = form.sys_enterpriseid || 0;
  332. let content = {
  333. ...form,
  334. };
  335. loading.value = true;
  336. $Http.basic({
  337. "id": "20230206091403",
  338. content
  339. }).then(res => {
  340. loading.value = false;
  341. console.log("提交申请单", res);
  342. if (res.code !== 1) {
  343. uni.showToast({ title: res.code !== 1 ? res.msg : "保存成功", icon: 'none', mask: res.code == 1 });
  344. } else {
  345. $Http.basic({
  346. id: 20230206101403,
  347. content: {
  348. sa_serviceorderid: res.data.sa_serviceorderid,
  349. backreason: "",
  350. issumbit: 1
  351. }
  352. }).then(res1 => {
  353. console.log("提交工单", res1);
  354. })
  355. if (form.isonlinesales) {
  356. uni.showModal({
  357. content: "预约申请已提交, 继续创建新的预约申请?",
  358. confirmText: '继续创建',
  359. cancelText: '返回',
  360. success: (success) => {
  361. if (success.confirm) {
  362. uni.redirectTo({
  363. url: '/pages/launchApplication/index',
  364. });
  365. } else {
  366. uni.navigateBack();
  367. }
  368. },
  369. })
  370. } else {
  371. uni.showModal({
  372. content: "预约申请已提交,立即前往还是继续创建?",
  373. confirmText: '立即前往',
  374. cancelText: '继续创建',
  375. success: (success) => {
  376. if (success.confirm) {
  377. uni.redirectTo({
  378. url: `/pages/generalServices/detail?id=${res.data.sa_serviceorderid}`,
  379. });
  380. } else {
  381. uni.redirectTo({
  382. url: '/pages/launchApplication/index',
  383. });
  384. }
  385. },
  386. })
  387. }
  388. }
  389. }).catch(err => {
  390. loading.value = false;
  391. console.error("保存工单失败", err);
  392. uni.showToast({ title: '保存失败,请稍后重试', icon: 'none' });
  393. });
  394. }
  395. },
  396. })
  397. })
  398. }
  399. function skuConfirm() {
  400. if (form.sku) {
  401. if (form.sku == '') return;
  402. querySkuing = true;
  403. $Http.basic({
  404. "id": 2025121515015903,
  405. "content": {
  406. "sku": form.sku
  407. }
  408. }).then(s => {
  409. console.log("预查询sku", s)
  410. if (s.code !== 1) {
  411. uni.showToast({ title: s.msg, icon: 'none' })
  412. form.sku = '';
  413. querySkuing = false;
  414. return
  415. };
  416. $Http.basic({
  417. "id": 20221215101003,
  418. "content": {
  419. "where": {
  420. "sku": form.sku
  421. }
  422. }
  423. }).then(res => {
  424. console.log("查询sku", res)
  425. uni.hideLoading();
  426. if (res.code !== 1) {
  427. uni.showToast({ title: res.msg, icon: 'none' })
  428. form.sku = '';
  429. querySkuing = false;
  430. return
  431. };
  432. if (res.data.length === 0 || res.data[0].sku !== form.sku) {
  433. uni.showToast({ title: '未查询到对应的产品信息,请确认序列号是否正确', icon: 'none' });
  434. form.sku = '';
  435. querySkuing = false;
  436. return;
  437. }
  438. changeItem(res.data[0]);
  439. })
  440. })
  441. } else {
  442. form.sku = '';
  443. }
  444. }
  445. let products = ref([]); // 产品列表
  446. function closePopup() {
  447. products.value = [];
  448. }
  449. function changeItem(item) {
  450. let list = ['sku', 'cardno', 'itemid', 'name', 'phonenumber', 'itemname', 'province', 'city', 'county', 'itemno', 'sa_customersid', 'address', 'warrantystatus'];
  451. list.forEach(key => {
  452. if (key == 'name') {
  453. form['customername'] = item[key] || form['customername'] || '';
  454. form['scenecontact'] = item[key] || form['scenecontact'] || '';
  455. } else if (key == 'phonenumber') {
  456. form['customerphonenumber'] = item[key] || form['customerphonenumber'] || '';
  457. form['scenecontactphonenumber'] = item[key] || form['scenecontactphonenumber'] || '';
  458. } else if (['province', 'city', 'county'].includes(key)) {
  459. form[key] = item[key] || form[key] || '';
  460. } else {
  461. form[key] = item[key] || '';
  462. }
  463. });
  464. querySkuing = false;
  465. console.log("选择产品", form);
  466. closePopup();
  467. }
  468. function openScan() {
  469. uni.scanCode({
  470. onlyFromCamera: true,
  471. scanType: ['qrCode', 'barCode'],
  472. success: (res) => {
  473. console.log("扫码结果", res);
  474. if (res.result) {
  475. form.sku = res.result;
  476. skuConfirm();
  477. } else {
  478. uni.showToast({ title: '扫码失败,请重试', icon: 'none' });
  479. }
  480. },
  481. fail: (err) => {
  482. console.error("扫码失败", err);
  483. uni.showToast({ title: '扫码失败,请重试', icon: 'none' });
  484. }
  485. });
  486. }
  487. </script>
  488. <style lang="scss" scoped>
  489. .content {
  490. width: 100vw;
  491. padding: 20px;
  492. box-sizing: border-box;
  493. min-height: 100vh;
  494. background: #fff;
  495. .picker {
  496. font-size: 28rpx;
  497. color: #606266;
  498. padding: 9px;
  499. border-radius: 8rpx;
  500. border: 1rpx solid #2979FF;
  501. color: #2979FF;
  502. }
  503. .title {
  504. font-size: 34rpx;
  505. color: #4773EE;
  506. margin: 20rpx 0;
  507. font-weight: bold;
  508. }
  509. .region {
  510. font-size: 28rpx;
  511. color: #606266;
  512. padding: 10px 9px;
  513. width: 280px;
  514. box-sizing: border-box;
  515. border-radius: 8rpx;
  516. border: 1rpx solid #dadbde !important;
  517. }
  518. }
  519. .product {
  520. padding: 20rpx;
  521. background: #fff;
  522. margin: 10rpx 0;
  523. border-radius: 8rpx;
  524. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  525. .itemname {
  526. font-size: 32rpx;
  527. color: #333;
  528. font-weight: bold;
  529. margin-bottom: 10rpx;
  530. }
  531. .row {
  532. font-size: 28rpx;
  533. color: #666;
  534. margin-top: 8rpx;
  535. }
  536. }
  537. .my-but {
  538. line-height: 44rpx;
  539. padding: 0 20rpx;
  540. background: #2979ff;
  541. color: #fff;
  542. border-radius: 8rpx;
  543. margin-right: 10rpx;
  544. font-size: 24rpx;
  545. }
  546. </style>