2 lines
18 KiB
JavaScript
2 lines
18 KiB
JavaScript
import{K as Mt,J as Ht,T as Kt,i as Bt,D as Ft,B as Ot,C as Rt,M as Gt,N as Jt,q as Qt,r as Wt,L as Xt,g as Yt,P as Zt,Q as te,V as ee,ab as le,ac as se,R as ae,e as ne,a9 as oe,aa as ie}from"./element-plus-B0TQYp6r.js";import{_ as re}from"./index.vue_vue_type_script_setup_true_lang-CwcSYDOM.js";import{w as mt}from"./@vue/runtime-dom-iFk_KP8y.js";import{X as ue,K as ct,S as de}from"./@element-plus/icons-vue-BAMXcVym.js";import{u as me}from"./usePaging-B_C_SZ2Z.js";import{r as C,i as A,_ as ce}from"./index-FMAV3lC6.js";import{f as fe,b as _e,d as pe,ak as m,I as f,a as l,aN as s,J as o,H as T,F as U,ap as j,O as i,aP as ye,G as h,A as Z}from"./@vue/runtime-core-C0pg79pw.js";import{r as M,y as p,a as ge,o as N}from"./@vue/reactivity-BIbyPIZJ.js";import{Q as r,p as ve,o as xe}from"./@vue/shared-mAAVTE9n.js";import"./lodash-es-C2A-Pj28.js";import"./@popperjs/core-C5az9QE8.js";import"./dayjs-DG77mNTn.js";import"./lodash-D3kF6u-c.js";import"./@ctrl/tinycolor-BuyEbX8F.js";import"./async-validator-CFA_igpM.js";import"./normalize-wheel-es-BQoi3Ox2.js";import"./jspdf-BsthCvR5.js";import"./@babel/runtime-BanGtE2-.js";import"./fflate-_ayOYiT1.js";import"./vue-router-CYz6RFzi.js";import"./pinia-Ba_jX6-d.js";import"./axios-C80V62Fs.js";import"./@vueuse/core-DIKi2bJB.js";import"./@vueuse/shared-D8934tfB.js";import"./css-color-function-DI01JAaZ.js";import"./balanced-match-BdS7OldZ.js";import"./color-B2zxaWkI.js";import"./clone-DBZ6_OiU.js";import"./color-convert-OrFsTA_V.js";import"./color-name-Dju3oUBS.js";import"./color-string-pUQDDJII.js";import"./ms-CzQ2E3wO.js";import"./vue-clipboard3-DByT_rEQ.js";import"./clipboard-CHgxszqY.js";import"./echarts-CZvD9OL_.js";import"./tslib-BDyQ-Jie.js";import"./zrender-BQyIY4j9.js";import"./highlight.js-Bxt7hFFy.js";import"./@highlightjs/vue-plugin-BVMzZUvF.js";function be(E){return C.get({url:"/qywx.customer/lists",params:E})}function we(){return C.post({url:"/qywx.customer/sync"})}function Se(){return C.get({url:"/qywx.customer/stats"})}function he(){return C.get({url:"/qywx.customer/todayArrival"})}function ke(E){return C.get({url:"/qywx.customer/todayArrivalList",params:E})}function Ce(){return C.get({url:"/qywx.customer/getSyncSettings"})}function Ee(E){return C.post({url:"/qywx.customer/saveSyncSettings",params:E})}const Ve={class:"qywx-customer-page p-4"},Ae={class:"flex items-center justify-between"},Te={class:"flex gap-2"},Ne={class:"grid grid-cols-4 gap-4 mb-4"},qe={class:"text-2xl font-bold text-primary"},ze={class:"flex items-center justify-between mb-1"},Ie={key:0,class:"text-xs text-gray-400"},De={class:"flex items-end gap-2"},$e={class:"text-2xl font-bold text-success leading-none"},Le=["title"],Pe={class:"mt-2 pt-2 border-t border-gray-100"},Ue={class:"text-lg font-semibold text-gray-800"},je={class:"text-sm font-medium"},Me={class:"flex items-center gap-2"},He={class:"font-medium"},Ke={class:"text-xs text-gray-400"},Be={key:0},Fe={key:1,class:"text-gray-400"},Oe={class:"flex justify-end mt-4"},Re={class:"flex items-center justify-between w-full pr-4"},Ge={class:"flex items-center gap-3"},Je={class:"px-1"},Qe={key:0,class:"mb-3"},We={class:"flex flex-wrap gap-1"},Xe={class:"flex items-start gap-2"},Ye={class:"flex-1 min-w-0"},Ze={class:"text-sm font-medium truncate"},tl={class:"text-xs text-gray-500 mt-0.5"},el={key:0,class:"ml-2"},ll={key:1,class:"ml-2 text-emerald-500"},sl={key:3,class:"mt-3 text-center"},al={key:0},nl={key:1,class:"text-gray-400"},ol=fe({__name:"qywx",setup(E){const q=N(!1),z=N(!1),J=N(!1),_=N(null),x=M({total:0,today:0,today_follow_staff:0,lastSync:"",syncStatus:"idle",syncStatusText:"未同步"}),ft=Z(()=>{switch(x.syncStatus){case"success":return"success";case"syncing":return"warning";case"failed":return"danger";default:return"info"}}),y=M({auto_sync:!1,interval:3600}),S=M({name:"",follow_user:""}),g=M({total:0,recent_time:0,hourly:new Array(24).fill(0),by_state:[]}),I=N(!1),H=N(!1),c=M({total:0,page_no:1,page_size:20,lists:[]}),_t=new Date().getHours(),pt=Z(()=>Math.max(1,...g.hourly));function yt(e){if(e<=0)return"2px";const t=e/pt.value;return Math.max(4,Math.round(t*32))+"px"}const gt=Z(()=>{const e=[];return g.hourly.forEach((t,n)=>{t>0&&e.push(`${String(n).padStart(2,"0")}:00 · ${t}`)}),e.length?e.join(" "):"今天还没有人进入"});async function K(e=!1){try{const t=await he();t&&(g.total=Number(t.total??0),g.recent_time=Number(t.recent_time??0),g.hourly=Array.isArray(t.hourly)&&t.hourly.length===24?t.hourly.map(n=>Number(n)||0):new Array(24).fill(0),g.by_state=Array.isArray(t.by_state)?t.by_state:[])}catch(t){console.error("加载今日进入分布失败",t)}e&&I.value&&(c.page_no=1,c.lists=[],await Q())}async function Q(){H.value=!0;try{const e=await ke({page_no:c.page_no,page_size:c.page_size});if(e){c.total=Number(e.total??0);const t=Array.isArray(e.lists)?e.lists:[];c.page_no===1?c.lists=t:c.lists.push(...t)}}catch(e){console.error("加载今日进入明细失败",e)}finally{H.value=!1}}async function tt(){I.value=!0,c.page_no=1,c.lists=[],await Promise.all([K(!1),Q()])}async function vt(){c.lists.length>=c.total||(c.page_no+=1,await Q())}function xt(e){if(!e||e<=0)return"";const t=new Date(e<1e12?e*1e3:e);return`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}function bt(e){if(!e||e<=0)return"—";const t=new Date(e<1e12?e*1e3:e);return`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}:${String(t.getSeconds()).padStart(2,"0")}`}let D=null,B=null;function W(){B!==null&&(clearInterval(B),B=null)}async function wt(e){return be(e)}const{pager:$,getLists:F,resetPage:X,resetParams:St}=me({fetchFun:wt,params:S});function ht(){S.name="",S.follow_user="",St()}function kt(){W();let e=0;B=window.setInterval(async()=>{e+=1,await O(),await F(),(x.syncStatus!=="syncing"||e>=120)&&(W(),q.value=!1,e>=120&&x.syncStatus==="syncing"?A.msgWarning("长时间仍为「同步中」,请刷新页面或查看服务器 runtime/log/qywx_sync.log(可能未安装 CLI php 或禁用了 exec)"):x.syncStatus==="failed"&&A.msgError("同步失败,请查看服务器 runtime/log/qywx_sync.log 或后台同步状态"))},3e3)}async function et(e){const t=(e==null?void 0:e.silent)===!0;q.value=!0;try{const n=await we();t||A.msgSuccess((n==null?void 0:n.message)||"操作成功"),await O(),await F(),n!=null&&n.background?kt():q.value=!1}catch(n){const d=(n==null?void 0:n.message)||(n==null?void 0:n.msg)||"同步失败";(!t||!String(d).includes("正在执行"))&&A.msgError(d),q.value=!1}}async function O(){try{const e=await Se();e&&typeof e=="object"&&Object.assign(x,e)}catch(e){console.error("加载统计失败",e)}}async function Ct(){try{const e=await Ce();e&&typeof e=="object"&&Object.assign(y,e),y.auto_sync&<()}catch(e){console.error("加载同步设置失败",e)}}async function Et(){try{await Ee(y),A.msgSuccess("保存成功"),z.value=!1,st(),y.auto_sync&<()}catch(e){A.msgError((e==null?void 0:e.message)||"保存失败")}}function lt(){D||(D=window.setInterval(()=>{et({silent:!0})},y.interval*1e3))}function st(){D&&(clearInterval(D),D=null)}function Vt(e){_.value=e,J.value=!0}function at(e){const t=String((e==null?void 0:e.admin_name)??"").trim(),n=String((e==null?void 0:e.userid)??"").trim(),d=String((e==null?void 0:e.name)??"").trim();return t||(d&&n?`${d}(${n})`:d||n||"—")}function R(e){const t=String((e==null?void 0:e.admin_name)??"").trim(),n=String((e==null?void 0:e.userid)??"").trim(),d=[];return t&&d.push("后台:"+t),n&&d.push("企微:"+n),d.join("|")}function nt(e){if(!e)return null;const t=Number(e.external_first_add_time??0);if(t>0)return t;const n=e.follow_users;if(Array.isArray(n)&&n.length>0){let d=0;for(const b of n){const v=Number((b==null?void 0:b.createtime)??0);v>0&&(d===0||v<d)&&(d=v)}if(d>0)return d}return e.create_time??null}function G(e){if(e===""||e===null||e===void 0)return"—";const t=Number(e),n=typeof e=="string"&&/^\d+$/.test(e.trim());let d;return typeof e=="number"?d=e<1e12?e*1e3:e:!Number.isNaN(t)&&n?d=t<1e12?t*1e3:t:d=new Date(e).getTime(),Number.isNaN(d)?"—":new Date(d).toLocaleString("zh-CN")}let L=null;function At(){L===null&&(L=window.setInterval(()=>{O(),K(I.value)},3e4))}function Tt(){L!==null&&(clearInterval(L),L=null)}return _e(()=>{F(),O(),Ct(),K(!1),At()}),pe(()=>{st(),W(),Tt()}),(e,t)=>{const n=Bt,d=Mt,b=Ht,v=Kt,ot=Rt,P=Ot,it=Ft,rt=Qt,k=Jt,ut=Wt,Nt=Gt,qt=re,zt=Yt,V=te,It=Zt,dt=ee,Dt=se,$t=le,Lt=ae,Pt=ne,w=ie,Ut=oe,jt=Xt;return m(),f("div",Ve,[l(b,{shadow:"never",class:"mb-4"},{header:s(()=>[o("div",Ae,[t[15]||(t[15]=o("span",{class:"text-lg font-semibold"},"企业微信客户管理",-1)),o("div",Te,[l(n,{type:"success",plain:"",onClick:tt},{icon:s(()=>[l(p(ue))]),default:s(()=>[t[12]||(t[12]=i(" 今日进入明细 ",-1))]),_:1}),l(n,{type:"primary",loading:q.value,onClick:t[0]||(t[0]=a=>et())},{icon:s(()=>[l(p(ct))]),default:s(()=>[t[13]||(t[13]=i(" 立即同步 ",-1))]),_:1},8,["loading"]),l(n,{onClick:t[1]||(t[1]=a=>z.value=!0)},{icon:s(()=>[l(p(de))]),default:s(()=>[t[14]||(t[14]=i(" 同步设置 ",-1))]),_:1})])])]),default:s(()=>[l(d,{title:"功能说明",type:"info",closable:!1,class:"mb-4"},{default:s(()=>[...t[16]||(t[16]=[o("div",{class:"text-sm"},[o("p",null,"自动从企业微信同步外部联系人(客户)信息,包括客户基本信息、跟进人等。"),o("p",{class:"mt-1"},"同步后的数据可用于患者信息匹配和自动关联。")],-1)])]),_:1}),o("div",Ne,[l(b,{shadow:"hover"},{default:s(()=>[t[17]||(t[17]=o("div",{class:"text-gray-500 text-sm mb-1"},"总客户数",-1)),o("div",qe,r(x.total),1)]),_:1}),l(b,{shadow:"hover",class:"today-arrival-card cursor-pointer",onClick:tt},{default:s(()=>[o("div",ze,[t[18]||(t[18]=o("span",{class:"text-gray-500 text-sm"},"今日新增",-1)),g.recent_time?(m(),f("span",Ie," 最近 "+r(xt(g.recent_time)),1)):T("",!0)]),o("div",De,[o("div",$e,r(x.today),1),t[19]||(t[19]=o("div",{class:"text-xs text-gray-400 pb-1"},"人",-1))]),o("div",{class:"hourly-bars mt-2",title:gt.value},[(m(!0),f(U,null,j(g.hourly,(a,u)=>(m(),f("div",{key:u,class:xe(["hourly-bar",{"is-empty":a===0,"is-current":u===p(_t)}]),style:ve({height:yt(a)})},null,6))),128))],8,Le),o("div",Pe,[t[20]||(t[20]=o("div",{class:"text-gray-500 text-xs mb-0.5"},"今日跟进人合计",-1)),o("div",Ue,r(x.today_follow_staff),1)])]),_:1}),l(b,{shadow:"hover"},{default:s(()=>[t[21]||(t[21]=o("div",{class:"text-gray-500 text-sm mb-1"},"最后同步",-1)),o("div",je,r(x.lastSync||"未同步"),1)]),_:1}),l(b,{shadow:"hover"},{default:s(()=>[t[22]||(t[22]=o("div",{class:"text-gray-500 text-sm mb-1"},"同步状态",-1)),l(v,{type:ft.value,size:"small"},{default:s(()=>[i(r(x.syncStatusText),1)]),_:1},8,["type"])]),_:1})])]),_:1}),l(b,{shadow:"never"},{default:s(()=>[l(it,{model:S,inline:"",class:"mb-4"},{default:s(()=>[l(P,{label:"客户名称"},{default:s(()=>[l(ot,{modelValue:S.name,"onUpdate:modelValue":t[2]||(t[2]=a=>S.name=a),placeholder:"搜索客户名称",clearable:"",onKeyup:mt(p(X),["enter"])},null,8,["modelValue","onKeyup"])]),_:1}),l(P,{label:"跟进人"},{default:s(()=>[l(ot,{modelValue:S.follow_user,"onUpdate:modelValue":t[3]||(t[3]=a=>S.follow_user=a),placeholder:"跟进人姓名",clearable:"",onKeyup:mt(p(X),["enter"])},null,8,["modelValue","onKeyup"])]),_:1}),l(P,null,{default:s(()=>[l(n,{type:"primary",onClick:p(X)},{default:s(()=>[...t[23]||(t[23]=[i("查询",-1)])]),_:1},8,["onClick"]),l(n,{onClick:ht},{default:s(()=>[...t[24]||(t[24]=[i("重置",-1)])]),_:1})]),_:1})]),_:1},8,["model"]),ye((m(),h(Nt,{data:p($).lists,stripe:""},{default:s(()=>[l(k,{label:"客户信息","min-width":"200"},{default:s(({row:a})=>[o("div",Me,[l(rt,{size:40,src:a.avatar},null,8,["src"]),o("div",null,[o("div",He,r(a.name),1),o("div",Ke,r(a.external_userid),1)])])]),_:1}),l(k,{label:"类型",width:"80"},{default:s(({row:a})=>[l(v,{size:"small"},{default:s(()=>[i(r(a.type===1?"微信":"企微"),1)]),_:2},1024)]),_:1}),l(k,{label:"性别",width:"60"},{default:s(({row:a})=>[i(r(a.gender===1?"男":a.gender===2?"女":"未知"),1)]),_:1}),l(k,{label:"跟进人","min-width":"150"},{default:s(({row:a})=>[a.follow_users&&a.follow_users.length?(m(),f("div",Be,[(m(!0),f(U,null,j(a.follow_users,(u,Y)=>(m(),h(ut,{key:(u.userid||"")+"-"+Y,disabled:!R(u),content:R(u),placement:"top"},{default:s(()=>[l(v,{size:"small",class:"mr-1 mb-1"},{default:s(()=>[i(r(at(u)),1)]),_:2},1024)]),_:2},1032,["disabled","content"]))),128))])):(m(),f("span",Fe,"—"))]),_:1}),l(k,{label:"添加时间",width:"160"},{default:s(({row:a})=>[i(r(G(nt(a))),1)]),_:1}),l(k,{label:"更新时间",width:"160"},{default:s(({row:a})=>[i(r(G(a.update_time)),1)]),_:1}),l(k,{label:"操作",width:"120",fixed:"right"},{default:s(({row:a})=>[l(n,{type:"primary",link:"",onClick:u=>Vt(a)},{default:s(()=>[...t[25]||(t[25]=[i("查看详情",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[jt,p($).loading]]),o("div",Oe,[l(qt,{modelValue:p($),"onUpdate:modelValue":t[4]||(t[4]=a=>ge($)?$.value=a:null),onChange:p(F)},null,8,["modelValue","onChange"])])]),_:1}),l(dt,{modelValue:z.value,"onUpdate:modelValue":t[8]||(t[8]=a=>z.value=a),title:"同步设置",width:"500px"},{footer:s(()=>[l(n,{onClick:t[7]||(t[7]=a=>z.value=!1)},{default:s(()=>[...t[27]||(t[27]=[i("取消",-1)])]),_:1}),l(n,{type:"primary",onClick:Et},{default:s(()=>[...t[28]||(t[28]=[i("保存",-1)])]),_:1})]),default:s(()=>[l(it,{model:y,"label-width":"120px"},{default:s(()=>[l(P,{label:"自动同步"},{default:s(()=>[l(zt,{modelValue:y.auto_sync,"onUpdate:modelValue":t[5]||(t[5]=a=>y.auto_sync=a)},null,8,["modelValue"]),t[26]||(t[26]=o("div",{class:"text-xs text-gray-400 mt-1"}," 开启后将定时自动同步企业微信客户数据 ",-1))]),_:1}),l(P,{label:"同步间隔"},{default:s(()=>[l(It,{modelValue:y.interval,"onUpdate:modelValue":t[6]||(t[6]=a=>y.interval=a),disabled:!y.auto_sync},{default:s(()=>[l(V,{label:"每小时",value:3600}),l(V,{label:"每2小时",value:7200}),l(V,{label:"每4小时",value:14400}),l(V,{label:"每6小时",value:21600}),l(V,{label:"每12小时",value:43200}),l(V,{label:"每天",value:86400})]),_:1},8,["modelValue","disabled"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"]),l(Pt,{modelValue:I.value,"onUpdate:modelValue":t[10]||(t[10]=a=>I.value=a),title:"今日进入明细",direction:"rtl",size:"520px","destroy-on-close":!1},{header:s(()=>[o("div",Re,[o("div",Ge,[t[29]||(t[29]=o("span",{class:"text-base font-semibold"},"今日进入明细",-1)),l(v,{type:"success",effect:"plain"},{default:s(()=>[i("共 "+r(c.total)+" 人",1)]),_:1})]),l(n,{link:"",type:"primary",loading:H.value,onClick:t[9]||(t[9]=a=>K(!0))},{icon:s(()=>[l(p(ct))]),default:s(()=>[t[30]||(t[30]=i(" 刷新 ",-1))]),_:1},8,["loading"])])]),default:s(()=>{var a;return[o("div",Je,[l(d,{type:"info",closable:!1,class:"mb-3","show-icon":""},{title:s(()=>[...t[31]||(t[31]=[o("span",{class:"text-xs"}," 一次推送 = 一个人进来;数据来源为企微回调流水表(INSERT IGNORE 幂等),与客户同步解耦,数字零误差。 ",-1)])]),_:1}),(a=g.by_state)!=null&&a.length?(m(),f("div",Qe,[t[32]||(t[32]=o("div",{class:"text-xs text-gray-500 mb-1"},"今日推广渠道 Top",-1)),o("div",We,[(m(!0),f(U,null,j(g.by_state,u=>(m(),h(v,{key:u.state||"_",size:"small",effect:"light",type:"success"},{default:s(()=>[i(r(u.state||"(无 state)")+" · "+r(u.count),1)]),_:2},1024))),128))])])):T("",!0),c.lists.length?(m(),h($t,{key:1,class:"mt-2"},{default:s(()=>[(m(!0),f(U,null,j(c.lists,u=>(m(),h(Dt,{key:u.id,timestamp:bt(u.event_time),placement:"top",type:"success",hollow:!1},{default:s(()=>[o("div",Xe,[l(rt,{size:32,src:u.customer_avatar||void 0},{default:s(()=>[i(r((u.customer_name||"?").slice(0,1)),1)]),_:2},1032,["src"]),o("div",Ye,[o("div",Ze,r(u.customer_name||u.external_userid||"(未知客户)"),1),o("div",tl,[o("span",null,"接待:"+r(u.admin_name||u.user_id||"—"),1),u.state?(m(),f("span",el,[t[33]||(t[33]=i(" 渠道:",-1)),l(v,{size:"small",type:"info",effect:"plain"},{default:s(()=>[i(r(u.state),1)]),_:2},1024)])):T("",!0),u.welcome_code?(m(),f("span",ll,"欢迎语")):T("",!0)])])])]),_:2},1032,["timestamp"]))),128))]),_:1})):(m(),h(Lt,{key:2,description:"今天还没有人进入","image-size":80})),c.total>c.lists.length?(m(),f("div",sl,[l(n,{loading:H.value,size:"small",onClick:vt},{default:s(()=>[i(" 加载更多(还剩 "+r(c.total-c.lists.length)+") ",1)]),_:1},8,["loading"])])):T("",!0)])]}),_:1},8,["modelValue"]),l(dt,{modelValue:J.value,"onUpdate:modelValue":t[11]||(t[11]=a=>J.value=a),title:"客户详情",width:"600px"},{default:s(()=>[_.value?(m(),h(Ut,{key:0,column:2,border:""},{default:s(()=>[l(w,{label:"客户名称"},{default:s(()=>[i(r(_.value.name),1)]),_:1}),l(w,{label:"External ID"},{default:s(()=>[i(r(_.value.external_userid),1)]),_:1}),l(w,{label:"性别"},{default:s(()=>[i(r(_.value.gender===1?"男":_.value.gender===2?"女":"未知"),1)]),_:1}),l(w,{label:"类型"},{default:s(()=>[i(r(_.value.type===1?"微信用户":"企业微信用户"),1)]),_:1}),l(w,{label:"企业名称",span:2},{default:s(()=>[i(r(_.value.corp_name||"—"),1)]),_:1}),l(w,{label:"职位",span:2},{default:s(()=>[i(r(_.value.position||"—"),1)]),_:1}),l(w,{label:"添加时间",span:2},{default:s(()=>[i(r(G(nt(_.value))),1)]),_:1}),l(w,{label:"更新时间",span:2},{default:s(()=>[i(r(G(_.value.update_time)),1)]),_:1}),l(w,{label:"跟进人",span:2},{default:s(()=>{var a;return[(a=_.value.follow_users)!=null&&a.length?(m(),f("div",al,[(m(!0),f(U,null,j(_.value.follow_users,(u,Y)=>(m(),h(ut,{key:(u.userid||"")+"-"+Y,disabled:!R(u),content:R(u),placement:"top"},{default:s(()=>[l(v,{size:"small",class:"mr-1 mb-1"},{default:s(()=>[i(r(at(u)),1)]),_:2},1024)]),_:2},1032,["disabled","content"]))),128))])):(m(),f("span",nl,"—"))]}),_:1})]),_:1})):T("",!0)]),_:1},8,["modelValue"])])}}}),Rl=ce(ol,[["__scopeId","data-v-80cc5404"]]);export{Rl as default};
|