Files
machartaa_admin_dist/dist/assets/index-3e52bf29.js
T
2026-06-06 11:30:51 +03:30

2 lines
19 KiB
JavaScript

import{_ as xe}from"./BasicMainCard-c6601f7c.js";import{_ as ge}from"./BasicModal.vue_vue_type_style_index_0_lang-fe75b677.js";import{_ as be}from"./BasicTextArea.vue_vue_type_style_index_0_lang-ead0dcb0.js";import{a as ee,_ as ye,u as G}from"./useBaseTable-ce8a2e7a.js";import{_ as te}from"./BasicInput.vue_vue_type_style_index_0_lang-54821870.js";import{_ as ae}from"./button.vue_vue_type_style_index_0_lang-cc92a672.js";import{_ as he,I as R,d as ne,g as I,h as $,x as we,D as f,o as P,c as S,F as Ie,a as t,b as o,t as D,q as ke,w as b,e as Z,j as h,G as V,k as X,H as Ae}from"./index-d35b2fe0.js";import{t as F}from"./useDataTime-a21b0163.js";import{I as B}from"./Icon-f953806c.js";import{g as Le}from"./index-40da6560.js";import{e as Y,g as J}from"./convert-67c23be8.js";import{T as W}from"./index-1ea05067.js";import{M as Re}from"./index-2f27e483.js";import{S as Ce}from"./index-b9c4c4f8.js";import{T as q}from"./shallowequal-ea4257d9.js";import{U as Pe}from"./index-b1ee5e27.js";import"./_plugin-vue_export-helper-43ffde73.js";import"./index-de9afa51.js";import"./Col-933c6a21.js";import"./vnode-aa932a38.js";import"./isPlainObject-31d795a5.js";import"./index-dad1078f.js";import"./FormItemContext-02f2f90e.js";import"./index-46a03291.js";import"./toArray-2d2bb2c2.js";import"./pickAttrs-389dae7d.js";import"./useState-5645ad4c.js";import"./index-63acc1cf.js";import"./usePrice-7afab779.js";import"./useRefs-07fc8b5a.js";import"./index-f397d805.js";function se(e,i){return Math.max(0,Math.round(e*(1-(i||0)/100)))}async function Se(e){const{TableEngineRequest:i}=await he(()=>import("./buildSupabaseQuery-6ebd7005.js"),["assets/buildSupabaseQuery-6ebd7005.js","assets/index-d35b2fe0.js","assets/index-ee24fe8b.css"]),l={...e};!l.sort&&!l.order&&(l.order="-sort_order");const a=await i(l,"subscription_plans");if(Array.isArray(a==null?void 0:a.rows)){const p=a.rows.map((g,m)=>({...g,index:m,final_price:se(Number(g.price),Number(g.discount_percent||0))}));return{...a,rows:p}}return a}async function Ne(e){const{limit:i=20,page:l=1,search:a}=e,{data:p,error:g}=await R.from("subscription_purchases").select("*, users(name, phone, first_name, last_name)",{count:"exact"}).order("created_at",{ascending:!1});if(g)throw g;let m=(p||[]).map((u,_)=>{const c=Array.isArray(u.users)?u.users[0]:u.users;let k="نامشخص";return c!=null&&c.name?k=c.name:c!=null&&c.first_name||c!=null&&c.last_name?k=`${c.first_name||""} ${c.last_name||""}`.trim():c!=null&&c.phone&&(k=c.phone),{...u,index:_,user_name:k,user_phone:(c==null?void 0:c.phone)||""}});if(a){const u=String(a).toLowerCase();m=m.filter(_=>(_.plan_title||"").toLowerCase().includes(u)||(_.user_name||"").toLowerCase().includes(u)||(_.user_phone||"").toLowerCase().includes(u)||(_.payment_status||"").toLowerCase().includes(u))}const w=(l-1)*i;return{rows:m.slice(w,w+i).map((u,_)=>({...u,index:w+_})),total:m.length,query:{...e,total:m.length,page:l,limit:i}}}async function Te(e){const{data:i,error:l}=await R.from("subscription_plans").insert([{title:e.title,description:e.description||null,image_url:e.image_url,price:e.price,discount_percent:e.discount_percent??0,duration_days:e.duration_days,is_active:e.is_active??!0,sort_order:e.sort_order??0}]).select().single();if(l)throw l;return i}async function ze(e,i){const{data:l,error:a}=await R.from("subscription_plans").update({title:i.title,description:i.description||null,image_url:i.image_url,price:i.price,discount_percent:i.discount_percent??0,duration_days:i.duration_days,is_active:i.is_active??!0,sort_order:i.sort_order??0,updated_at:new Date().toISOString()}).eq("id",e).select();if(a)throw a;return l}async function Be(e){const{error:i}=await R.from("subscription_plans").delete().eq("id",e);if(i)throw i}async function Ue(e,i){const{data:l,error:a}=await R.from("subscription_plans").update({is_active:i,updated_at:new Date().toISOString()}).eq("id",e).select();if(a)throw a;return l}function Q(e){return Number(e||0).toLocaleString("fa-IR")}const $e=[{title:"ردیف",dataIndex:"id",key:"id",filterable:!1,width:70,align:"center",customRender:e=>(e.record.index??0)+1},{title:"عنوان",dataIndex:"title",key:"title"},{title:"مدت (روز)",dataIndex:"duration_days",key:"duration_days",width:100,align:"center"},{title:"قیمت (ریال)",dataIndex:"price",key:"price",customRender:e=>Q(e.record.price)},{title:"تخفیف %",dataIndex:"discount_percent",key:"discount_percent",width:90,align:"center"},{title:"قیمت نهایی",dataIndex:"final_price",key:"final_price",customRender:e=>Q(e.record.final_price)},{title:"فعال",dataIndex:"is_active",key:"is_active",customRender:e=>e.record.is_active?"بله":"خیر"},{title:"ترتیب",dataIndex:"sort_order",key:"sort_order",width:80,align:"center"},{title:"ایجاد",dataIndex:"created_at",key:"created_at",customRender:e=>F(e.record.created_at)},{title:"عملیات",dataIndex:"action",key:"action",slot:"action",filterable:!1,align:"center"}];function De(e){return Number(e||0).toLocaleString("fa-IR")}const Ee={pending:"در انتظار",paid:"پرداخت شده",failed:"ناموفق",cancelled:"لغو شده"},Me={pending:"در انتظار",active:"فعال",expired:"منقضی",cancelled:"لغو شده"},Oe=[{title:"ردیف",dataIndex:"id",key:"id",filterable:!1,width:70,align:"center",customRender:e=>(e.record.index??0)+1},{title:"کاربر",dataIndex:"user_name",key:"user_name"},{title:"موبایل",dataIndex:"user_phone",key:"user_phone"},{title:"پلن",dataIndex:"plan_title",key:"plan_title"},{title:"مبلغ",dataIndex:"final_price",key:"final_price",customRender:e=>De(e.record.final_price)},{title:"پرداخت",dataIndex:"payment_status",key:"payment_status",customRender:e=>Ee[e.record.payment_status]||e.record.payment_status},{title:"وضعیت",dataIndex:"status",key:"status",customRender:e=>Me[e.record.status]||e.record.status},{title:"انقضا",dataIndex:"expires_at",key:"expires_at",customRender:e=>e.record.expires_at?F(e.record.expires_at):"-"},{title:"تاریخ خرید",dataIndex:"created_at",key:"created_at",customRender:e=>F(e.record.created_at)}],L={ZARINPAL_MERCHANT_ID:"zarinpal_merchant_id",ZARINPAL_SANDBOX:"zarinpal_sandbox",SUBSCRIPTION_CALLBACK_URL:"subscription_app_callback_url",ZARINPAL_ENABLED:"zarinpal_enabled"},qe=Object.values(L);function Fe(e){const i=(e[L.ZARINPAL_SANDBOX]||"no").toLowerCase(),l=(e[L.ZARINPAL_ENABLED]||"yes").toLowerCase();return{zarinpal_merchant_id:e[L.ZARINPAL_MERCHANT_ID]||"",zarinpal_sandbox:i==="yes"||i==="true"||i==="1",zarinpal_enabled:l!=="no"&&l!=="false"&&l!=="0",subscription_app_callback_url:e[L.SUBSCRIPTION_CALLBACK_URL]||"https://macharta.ir"}}async function U(e,i){const{data:l,error:a}=await R.from("configs").select("id").eq("key",e).maybeSingle();if(a)throw a;if(l!=null&&l.id){const{data:m,error:w}=await R.from("configs").update({value:i}).eq("key",e).select("id");if(w)throw w;if(!(m!=null&&m.length))throw new Error("ذخیره انجام نشد. لطفاً migration دسترسی configs را در Supabase اجرا کنید.");return}const{data:p,error:g}=await R.from("configs").insert({key:e,value:i}).select("id");if(g)throw g;if(!(p!=null&&p.length))throw new Error("ایجاد تنظیم انجام نشد. لطفاً migration دسترسی configs را در Supabase اجرا کنید.")}async function ie(){const{data:e,error:i}=await R.from("configs").select("key, value").in("key",qe);if(i)throw i;const l=(e||[]).reduce((a,p)=>(a[p.key]=p.value??"",a),{});return Fe(l)}async function Ze(e){return await U(L.ZARINPAL_MERCHANT_ID,e.zarinpal_merchant_id.trim()),await U(L.ZARINPAL_SANDBOX,e.zarinpal_sandbox?"yes":"no"),await U(L.ZARINPAL_ENABLED,e.zarinpal_enabled?"yes":"no"),await U(L.SUBSCRIPTION_CALLBACK_URL,e.subscription_app_callback_url.trim().replace(/\/$/,"")),ie()}const Ke={class:"max-w-2xl space-y-4"},je=t("p",{class:"text-sm text-gray-600 mb-4"}," کد مرچنت و آدرس بازگشت از درگاه در اینجا تنظیم می‌شود. اپ کاربر از همین تنظیمات برای اتصال به زرین‌پال استفاده می‌کند. ",-1),He={key:0,class:"py-8 text-center"},Ge=t("div",{class:"mb-1 text-sm text-gray-600"},"کد مرچنت زرین‌پال (Merchant ID)",-1),Ve=t("div",{class:"mb-1 text-sm text-gray-600"},"آدرس بازگشت از درگاه (URL اپ کاربر)",-1),Xe=t("div",{class:"text-xs text-gray-500 mt-1"},[Z(" مسیر callback به‌صورت خودکار اضافه می‌شود: "),t("code",null,"/subscriptions/callback")],-1),Ye={class:"flex items-center gap-3"},Je=t("span",{class:"text-sm"},"فعال بودن درگاه زرین‌پال",-1),We={class:"flex items-center gap-3"},Qe=t("span",{class:"text-sm"},"حالت تست (Sandbox)",-1),et=ne({__name:"PaymentGatewaySettings",setup(e){const i=I(!0),l=I(!1),a=I({zarinpal_merchant_id:"",zarinpal_sandbox:!1,zarinpal_enabled:!0,subscription_app_callback_url:"https://macharta.ir"}),p=$(()=>{var v;return a.value.zarinpal_enabled?a.value.zarinpal_sandbox?!0:!!((v=a.value.zarinpal_merchant_id)!=null&&v.trim()):!1}),g=$(()=>{var v;return a.value.zarinpal_enabled?a.value.zarinpal_sandbox?"حالت تست فعال است — پرداخت از sandbox زرین‌پال انجام می‌شود.":(v=a.value.zarinpal_merchant_id)!=null&&v.trim()?"درگاه برای پرداخت واقعی آماده است.":"کد مرچنت وارد نشده — درگاه آماده پرداخت واقعی نیست.":"درگاه غیرفعال است — کاربران نمی‌توانند پرداخت کنند."}),m=$(()=>p.value?"bg-green-50 border-green-200 text-green-800":"bg-amber-50 border-amber-200 text-amber-800");we(async()=>{try{a.value=await ie()}catch(v){f.error((v==null?void 0:v.message)||"خطا در بارگذاری تنظیمات")}finally{i.value=!1}});async function w(){var v,u;if(!((v=a.value.subscription_app_callback_url)!=null&&v.trim())){f.warning("آدرس بازگشت از درگاه الزامی است");return}if(a.value.zarinpal_enabled&&!a.value.zarinpal_sandbox&&!((u=a.value.zarinpal_merchant_id)!=null&&u.trim())){f.warning("برای پرداخت واقعی، کد مرچنت الزامی است");return}l.value=!0;try{a.value=await Ze(a.value),f.success("تنظیمات درگاه ذخیره شد")}catch(_){f.error((_==null?void 0:_.message)||"خطا در ذخیره")}finally{l.value=!1}}return(v,u)=>{const _=te,c=ee,k=ae;return P(),S("div",Ke,[je,i.value?(P(),S("div",He,"در حال بارگذاری...")):(P(),S(Ie,{key:1},[t("div",null,[Ge,o(_,{value:a.value.zarinpal_merchant_id,"onUpdate:value":u[0]||(u[0]=r=>a.value.zarinpal_merchant_id=r),placeholder:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"},null,8,["value"])]),t("div",null,[Ve,o(_,{value:a.value.subscription_app_callback_url,"onUpdate:value":u[1]||(u[1]=r=>a.value.subscription_app_callback_url=r),placeholder:"https://macharta.ir"},null,8,["value"]),Xe]),t("div",Ye,[o(c,{value:a.value.zarinpal_enabled,"onUpdate:value":u[2]||(u[2]=r=>a.value.zarinpal_enabled=r)},null,8,["value"]),Je]),t("div",We,[o(c,{value:a.value.zarinpal_sandbox,"onUpdate:value":u[3]||(u[3]=r=>a.value.zarinpal_sandbox=r)},null,8,["value"]),Qe]),t("div",{class:ke(["rounded-lg border p-3 text-sm",m.value])},D(g.value),3),o(k,{type:"primary",loading:l.value,onClick:w},{default:b(()=>[Z(" ذخیره تنظیمات درگاه ")]),_:1},8,["loading"])],64))])}}}),tt={class:"flex justify-between items-center mb-4"},at=t("h2",null,"مدیریت اشتراک‌ها",-1),nt={class:"gap-2 flex justify-center"},st=t("span",null,"حذف",-1),it=t("span",null,"ویرایش",-1),rt=t("div",{class:"mb-4"},[t("h2",null,"لیست خرید اشتراک")],-1),lt=t("div",{class:"mb-4"},[t("h2",null,"تنظیمات درگاه پرداخت")],-1),ot={class:"space-y-4 relative"},ct={key:0,class:"absolute inset-0 bg-white/60 z-10 flex items-center justify-center"},ut={class:"grid grid-cols-2 gap-4"},dt=t("div",{class:"mb-1 text-sm text-gray-600"},"عنوان اشتراک",-1),_t=t("div",{class:"mb-1 text-sm text-gray-600"},"مدت اشتراک (روز)",-1),pt={class:"grid grid-cols-3 gap-4"},mt=t("div",{class:"mb-1 text-sm text-gray-600"},"مبلغ (ریال)",-1),vt=t("div",{class:"mb-1 text-sm text-gray-600"},"تخفیف (درصد)",-1),ft=t("div",{class:"mb-1 text-sm text-gray-600"},"قیمت نهایی (ریال)",-1),xt={class:"mt-2 font-semibold text-green-700"},gt={class:"grid grid-cols-2 gap-4"},bt=t("div",{class:"mb-1 text-sm text-gray-600"},"ترتیب نمایش",-1),yt=t("div",{class:"mb-1 text-sm text-gray-600"},"وضعیت",-1),ht={class:"flex items-center gap-2 mt-2"},wt={class:"text-sm text-gray-600"},It=t("div",{class:"mb-1 text-sm text-gray-600"},"توضیحات",-1),kt={class:"flex justify-center"},At=t("div",{class:"mb-1 text-sm text-gray-600"},"تصویر اشتراک",-1),Lt={key:0},Rt=t("div",null,"آپلود تصویر",-1),ia=ne({__name:"index",setup(e){const i=W,l=W.TabPane,a=I("plans"),p=I(!1),g=I(!1),m=I(null),[w,v]=G(),[u]=G(),_=I([]),c=I(0),k=()=>({title:"",description:"",image_url:null,price:0,discount_percent:0,duration_days:30,is_active:!0,sort_order:0}),r=I(k()),re=$(()=>se(Number(r.value.price),Number(r.value.discount_percent)).toLocaleString("fa-IR")),le={columns:$e,api:Se,defaultPageLimit:20},oe={columns:Oe,api:Ne,defaultPageLimit:20};function K(){r.value=k(),_.value=[]}function ce(){g.value=!1,m.value=null,K(),p.value=!0}function j(){p.value=!1,K()}function ue(d){return d.type.startsWith("image/")?d.size/1024/1024>=5?(f.error("حجم تصویر باید کمتر از 5MB باشد"),!1):!0:(f.error("فقط فایل تصویری مجاز است"),!1)}async function de(d){const{file:n,onSuccess:C,onError:y,onProgress:A}=d,T=new FormData;T.append("file",n);const E=`${Ae}/upload/machartaa-img`;c.value++,await new Promise((M,N)=>{const s=new XMLHttpRequest;s.open("POST",E);const z=Le()||localStorage.getItem("tamin_token")||"";s.setRequestHeader("Authorization",`Bearer ${z}`),s.upload.onprogress=x=>{x.lengthComputable&&(A==null||A({percent:Math.round(x.loaded/x.total*100)}))},s.onload=()=>{if(s.status>=200&&s.status<300)try{const x=JSON.parse(s.responseText||"{}"),fe=x.full_src||x.url||x.src||x.path||x.data&&(x.data.full_src||x.data.url||x.data.src||x.data.path)||"",O=Y(fe),H=J(O);r.value.image_url=O,_.value=H?[{uid:`${Date.now()}`,name:"image.jpg",status:"done",url:H,response:{path:O}}]:[],C==null||C(x,s),f.success("تصویر با موفقیت آپلود شد!"),M()}catch(x){y==null||y(x,s),N(x)}else y==null||y(new Error("خطا در آپلود تصویر"),s),N(new Error("خطا در آپلود تصویر"))},s.onerror=()=>{y==null||y(new Error("خطا در آپلود تصویر"),s),N(new Error("خطا در آپلود تصویر"))},s.onloadend=()=>{c.value=Math.max(0,c.value-1)},s.send(T)})}async function _e(){var d;if(c.value>0){f.warning("لطفاً تا پایان آپلود صبر کنید");return}if(!((d=r.value.title)!=null&&d.trim())){f.warning("عنوان الزامی است");return}if(!r.value.duration_days||Number(r.value.duration_days)<1){f.warning("مدت اشتراک باید حداقل ۱ روز باشد");return}try{const n={...r.value,price:Number(r.value.price)||0,discount_percent:Number(r.value.discount_percent)||0,duration_days:Number(r.value.duration_days),sort_order:Number(r.value.sort_order)||0};g.value&&m.value?(await ze(m.value,n),f.success("اشتراک ویرایش شد")):(await Te(n),f.success("اشتراک افزوده شد")),j(),await v()}catch(n){f.error((n==null?void 0:n.message)||"خطا در ذخیره")}}function pe(d){g.value=!0,m.value=d.id;const n=Y(d.image_url)||null;r.value={title:d.title||"",description:d.description||"",image_url:n,price:d.price||0,discount_percent:d.discount_percent||0,duration_days:d.duration_days||30,is_active:d.is_active??!0,sort_order:d.sort_order??0};const C=n?J(n):null;_.value=C?[{uid:"-1",name:"image.jpg",status:"done",url:C,response:{path:n}}]:[],p.value=!0}function me(d){Re.confirm({title:"حذف اشتراک",content:`آیا از حذف «${d.title}» مطمئن هستید؟`,okText:"بله، حذف کن",cancelText:"انصراف",okType:"danger",centered:!0,onOk:async()=>{try{await Be(d.id),f.success("حذف شد"),await v()}catch(n){f.error((n==null?void 0:n.message)||"خطا در حذف")}}})}async function ve(d){try{await Ue(d.id,!d.is_active),f.success("وضعیت به‌روز شد"),await v()}catch(n){f.error((n==null?void 0:n.message)||"خطا")}}return(d,n)=>{const C=ae,y=ye,A=te,T=ee,E=be,M=ge,N=xe;return P(),S("div",null,[o(N,null,{default:b(()=>[o(h(i),{activeKey:a.value,"onUpdate:activeKey":n[0]||(n[0]=s=>a.value=s)},{default:b(()=>[o(h(l),{key:"plans",tab:"پلن‌های اشتراک"},{default:b(()=>[t("div",tt,[at,o(C,{type:"primary",onClick:ce},{default:b(()=>[Z("افزودن اشتراک")]),_:1})]),o(y,V(le,{ref:"table",onRegister:h(w)}),{action:b(({record:s})=>[t("div",nt,[o(h(q),{class:"cursor-pointer"},{title:b(()=>[t("span",null,D(s.is_active?"غیرفعال کردن":"فعال کردن"),1)]),default:b(()=>[o(B,{icon:s.is_active?"vuesax-linear:eye-slash":"vuesax-linear:eye",color:s.is_active?"#F59E0B":"#16A34A",onClick:z=>ve(s)},null,8,["icon","color","onClick"])]),_:2},1024),o(h(q),{class:"cursor-pointer"},{title:b(()=>[st]),default:b(()=>[o(B,{icon:"vuesax-linear:trash",color:"#DC2626",onClick:z=>me(s)},null,8,["onClick"])]),_:2},1024),o(h(q),{class:"cursor-pointer"},{title:b(()=>[it]),default:b(()=>[o(B,{icon:"vuesax-linear:edit",color:"#1D4ED8",onClick:z=>pe(s)},null,8,["onClick"])]),_:2},1024)])]),_:1},16,["onRegister"])]),_:1}),o(h(l),{key:"purchases",tab:"خریدهای کاربران"},{default:b(()=>[rt,o(y,V(oe,{onRegister:h(u)}),null,16,["onRegister"])]),_:1}),o(h(l),{key:"gateway",tab:"تنظیمات درگاه (زرین‌پال)"},{default:b(()=>[lt,o(et)]),_:1})]),_:1},8,["activeKey"]),o(M,{visible:p.value,"onUpdate:visible":n[9]||(n[9]=s=>p.value=s),title:g.value?"ویرایش اشتراک":"افزودن اشتراک",onOk:_e,onCancel:j,width:"70%",confirmLoading:c.value>0},{default:b(()=>[t("div",ot,[c.value>0?(P(),S("div",ct,[o(h(Ce),{size:"large"})])):X("",!0),t("div",ut,[t("div",null,[dt,o(A,{value:r.value.title,"onUpdate:value":n[1]||(n[1]=s=>r.value.title=s),placeholder:"مثلاً اشتراک یک ماهه"},null,8,["value"])]),t("div",null,[_t,o(A,{value:r.value.duration_days,"onUpdate:value":n[2]||(n[2]=s=>r.value.duration_days=s),type:"number",min:"1",placeholder:"30"},null,8,["value"])])]),t("div",pt,[t("div",null,[mt,o(A,{value:r.value.price,"onUpdate:value":n[3]||(n[3]=s=>r.value.price=s),type:"number",min:"0",placeholder:"100000"},null,8,["value"])]),t("div",null,[vt,o(A,{value:r.value.discount_percent,"onUpdate:value":n[4]||(n[4]=s=>r.value.discount_percent=s),type:"number",min:"0",max:"100",placeholder:"0"},null,8,["value"])]),t("div",null,[ft,t("div",xt,D(re.value),1)])]),t("div",gt,[t("div",null,[bt,o(A,{value:r.value.sort_order,"onUpdate:value":n[5]||(n[5]=s=>r.value.sort_order=s),type:"number",placeholder:"0"},null,8,["value"])]),t("div",null,[yt,t("div",ht,[o(T,{value:r.value.is_active,"onUpdate:value":n[6]||(n[6]=s=>r.value.is_active=s)},null,8,["value"]),t("span",wt,D(r.value.is_active?"فعال":"غیرفعال"),1)])])]),t("div",null,[It,o(E,{value:r.value.description,"onUpdate:value":n[7]||(n[7]=s=>r.value.description=s),placeholder:"توضیحات اشتراک",rows:4},null,8,["value"])]),t("div",kt,[t("div",null,[At,o(h(Pe),{"file-list":_.value,"onUpdate:fileList":n[8]||(n[8]=s=>_.value=s),"before-upload":ue,"custom-request":de,accept:"image/*","max-count":1,"list-type":"picture-card"},{default:b(()=>[_.value.length<1?(P(),S("div",Lt,[o(B,{icon:"vuesax-linear:image",class:"text-2xl mb-2"}),Rt])):X("",!0)]),_:1},8,["file-list"])])])])]),_:1},8,["visible","title","confirmLoading"])]),_:1})])}}});export{ia as default};